mirror of
https://github.com/XRPLF/rippled.git
synced 2026-07-27 00:50:45 +00:00
Compare commits
1 Commits
3.1.3
...
dangell7/s
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dc8a689a20 |
@@ -33,6 +33,5 @@ slack_app: false
|
|||||||
|
|
||||||
ignore:
|
ignore:
|
||||||
- "src/test/"
|
- "src/test/"
|
||||||
- "src/tests/"
|
|
||||||
- "include/xrpl/beast/test/"
|
- "include/xrpl/beast/test/"
|
||||||
- "include/xrpl/beast/unit_test/"
|
- "include/xrpl/beast/unit_test/"
|
||||||
|
|||||||
30
.github/actions/build-deps/action.yml
vendored
30
.github/actions/build-deps/action.yml
vendored
@@ -10,40 +10,24 @@ inputs:
|
|||||||
build_type:
|
build_type:
|
||||||
description: 'The build type to use ("Debug", "Release").'
|
description: 'The build type to use ("Debug", "Release").'
|
||||||
required: true
|
required: true
|
||||||
build_nproc:
|
|
||||||
description: "The number of processors to use for building."
|
|
||||||
required: true
|
|
||||||
force_build:
|
force_build:
|
||||||
description: 'Force building of all dependencies ("true", "false").'
|
description: 'Force building of all dependencies ("true", "false").'
|
||||||
required: false
|
required: false
|
||||||
default: "false"
|
default: "false"
|
||||||
log_verbosity:
|
|
||||||
description: "The logging verbosity."
|
|
||||||
required: false
|
|
||||||
default: "verbose"
|
|
||||||
|
|
||||||
runs:
|
runs:
|
||||||
using: composite
|
using: composite
|
||||||
steps:
|
steps:
|
||||||
- name: Install Conan dependencies
|
- name: Install Conan dependencies
|
||||||
shell: bash
|
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: |
|
run: |
|
||||||
echo 'Installing dependencies.'
|
echo 'Installing dependencies.'
|
||||||
mkdir -p "${BUILD_DIR}"
|
mkdir -p ${{ inputs.build_dir }}
|
||||||
cd "${BUILD_DIR}"
|
cd ${{ inputs.build_dir }}
|
||||||
conan install \
|
conan install \
|
||||||
--output-folder . \
|
--output-folder . \
|
||||||
--build="${BUILD_OPTION}" \
|
--build ${{ inputs.force_build == 'true' && '"*"' || 'missing' }} \
|
||||||
--options:host='&:tests=True' \
|
--options:host '&:tests=True' \
|
||||||
--options:host='&:xrpld=True' \
|
--options:host '&:xrpld=True' \
|
||||||
--settings:all build_type="${BUILD_TYPE}" \
|
--settings:all build_type=${{ inputs.build_type }} \
|
||||||
--conf:all tools.build:jobs=${BUILD_NPROC} \
|
--format=json ..
|
||||||
--conf:all tools.build:verbosity="${LOG_VERBOSITY}" \
|
|
||||||
--conf:all tools.compilation:verbosity="${LOG_VERBOSITY}" \
|
|
||||||
..
|
|
||||||
|
|||||||
96
.github/actions/build-test/action.yml
vendored
Normal file
96
.github/actions/build-test/action.yml
vendored
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
# This action build and tests the binary. The Conan dependencies must have
|
||||||
|
# already been installed (see the build-deps action).
|
||||||
|
name: Build and Test
|
||||||
|
description: "Build and test the binary."
|
||||||
|
|
||||||
|
# Note that actions do not support 'type' and all inputs are strings, see
|
||||||
|
# https://docs.github.com/en/actions/reference/workflows-and-actions/metadata-syntax#inputs.
|
||||||
|
inputs:
|
||||||
|
build_dir:
|
||||||
|
description: "The directory where to build."
|
||||||
|
required: true
|
||||||
|
build_only:
|
||||||
|
description: 'Whether to only build or to build and test the code ("true", "false").'
|
||||||
|
required: false
|
||||||
|
default: "false"
|
||||||
|
build_type:
|
||||||
|
description: 'The build type to use ("Debug", "Release").'
|
||||||
|
required: true
|
||||||
|
cmake_args:
|
||||||
|
description: "Additional arguments to pass to CMake."
|
||||||
|
required: false
|
||||||
|
default: ""
|
||||||
|
cmake_target:
|
||||||
|
description: "The CMake target to build."
|
||||||
|
required: true
|
||||||
|
codecov_token:
|
||||||
|
description: "The Codecov token to use for uploading coverage reports."
|
||||||
|
required: false
|
||||||
|
default: ""
|
||||||
|
os:
|
||||||
|
description: 'The operating system to use for the build ("linux", "macos", "windows").'
|
||||||
|
required: true
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: composite
|
||||||
|
steps:
|
||||||
|
- name: Configure CMake
|
||||||
|
shell: bash
|
||||||
|
working-directory: ${{ inputs.build_dir }}
|
||||||
|
run: |
|
||||||
|
echo 'Configuring CMake.'
|
||||||
|
cmake \
|
||||||
|
-G '${{ inputs.os == 'windows' && 'Visual Studio 17 2022' || 'Ninja' }}' \
|
||||||
|
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \
|
||||||
|
-DCMAKE_BUILD_TYPE=${{ inputs.build_type }} \
|
||||||
|
${{ inputs.cmake_args }} \
|
||||||
|
..
|
||||||
|
- name: Build the binary
|
||||||
|
shell: bash
|
||||||
|
working-directory: ${{ inputs.build_dir }}
|
||||||
|
run: |
|
||||||
|
echo 'Building binary.'
|
||||||
|
cmake \
|
||||||
|
--build . \
|
||||||
|
--config ${{ inputs.build_type }} \
|
||||||
|
--parallel $(nproc) \
|
||||||
|
--target ${{ inputs.cmake_target }}
|
||||||
|
- name: Check linking
|
||||||
|
if: ${{ inputs.os == 'linux' }}
|
||||||
|
shell: bash
|
||||||
|
working-directory: ${{ inputs.build_dir }}
|
||||||
|
run: |
|
||||||
|
echo 'Checking linking.'
|
||||||
|
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 voidstar
|
||||||
|
if: ${{ contains(inputs.cmake_args, '-Dvoidstar=ON') }}
|
||||||
|
shell: bash
|
||||||
|
working-directory: ${{ inputs.build_dir }}
|
||||||
|
run: |
|
||||||
|
echo 'Verifying presence of instrumentation.'
|
||||||
|
./rippled --version | grep libvoidstar
|
||||||
|
- name: Test the binary
|
||||||
|
if: ${{ inputs.build_only == 'false' }}
|
||||||
|
shell: bash
|
||||||
|
working-directory: ${{ inputs.build_dir }}/${{ inputs.os == 'windows' && inputs.build_type || '' }}
|
||||||
|
run: |
|
||||||
|
echo 'Testing binary.'
|
||||||
|
./rippled --unittest --unittest-jobs $(nproc)
|
||||||
|
ctest -j $(nproc) --output-on-failure
|
||||||
|
- 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: ${{ inputs.codecov_token }}
|
||||||
|
verbose: true
|
||||||
43
.github/actions/print-env/action.yml
vendored
43
.github/actions/print-env/action.yml
vendored
@@ -1,43 +0,0 @@
|
|||||||
name: Print build environment
|
|
||||||
description: "Print environment and some tooling versions"
|
|
||||||
|
|
||||||
runs:
|
|
||||||
using: composite
|
|
||||||
steps:
|
|
||||||
- name: Check configuration (Windows)
|
|
||||||
if: ${{ runner.os == 'Windows' }}
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
echo 'Checking environment variables.'
|
|
||||||
set
|
|
||||||
|
|
||||||
echo 'Checking CMake version.'
|
|
||||||
cmake --version
|
|
||||||
|
|
||||||
echo 'Checking Conan version.'
|
|
||||||
conan --version
|
|
||||||
|
|
||||||
- name: Check configuration (Linux and macOS)
|
|
||||||
if: ${{ runner.os == 'Linux' || runner.os == 'macOS' }}
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
echo 'Checking path.'
|
|
||||||
echo ${PATH} | tr ':' '\n'
|
|
||||||
|
|
||||||
echo 'Checking environment variables.'
|
|
||||||
env | sort
|
|
||||||
|
|
||||||
echo 'Checking CMake version.'
|
|
||||||
cmake --version
|
|
||||||
|
|
||||||
echo 'Checking compiler version.'
|
|
||||||
${{ runner.os == 'Linux' && '${CC}' || 'clang' }} --version
|
|
||||||
|
|
||||||
echo 'Checking Conan version.'
|
|
||||||
conan --version
|
|
||||||
|
|
||||||
echo 'Checking Ninja version.'
|
|
||||||
ninja --version
|
|
||||||
|
|
||||||
echo 'Checking nproc version.'
|
|
||||||
nproc --version
|
|
||||||
7
.github/actions/setup-conan/action.yml
vendored
7
.github/actions/setup-conan/action.yml
vendored
@@ -35,12 +35,9 @@ runs:
|
|||||||
|
|
||||||
- name: Set up Conan remote
|
- name: Set up Conan remote
|
||||||
shell: bash
|
shell: bash
|
||||||
env:
|
|
||||||
CONAN_REMOTE_NAME: ${{ inputs.conan_remote_name }}
|
|
||||||
CONAN_REMOTE_URL: ${{ inputs.conan_remote_url }}
|
|
||||||
run: |
|
run: |
|
||||||
echo "Adding Conan remote '${CONAN_REMOTE_NAME}' at '${CONAN_REMOTE_URL}'."
|
echo "Adding Conan remote '${{ inputs.conan_remote_name }}' at ${{ inputs.conan_remote_url }}."
|
||||||
conan remote add --index 0 --force "${CONAN_REMOTE_NAME}" "${CONAN_REMOTE_URL}"
|
conan remote add --index 0 --force ${{ inputs.conan_remote_name }} ${{ inputs.conan_remote_url }}
|
||||||
|
|
||||||
echo 'Listing Conan remotes.'
|
echo 'Listing Conan remotes.'
|
||||||
conan remote list
|
conan remote list
|
||||||
|
|||||||
6
.github/scripts/levelization/README.md
vendored
6
.github/scripts/levelization/README.md
vendored
@@ -72,15 +72,15 @@ It generates many files of [results](results):
|
|||||||
desired as described above. In a perfect repo, this file will be
|
desired as described above. In a perfect repo, this file will be
|
||||||
empty.
|
empty.
|
||||||
This file is committed to the repo, and is used by the [levelization
|
This file is committed to the repo, and is used by the [levelization
|
||||||
Github workflow](../../workflows/reusable-check-levelization.yml) to validate
|
Github workflow](../../workflows/check-levelization.yml) to validate
|
||||||
that nothing changed.
|
that nothing changed.
|
||||||
- [`ordering.txt`](results/ordering.txt): A list showing relationships
|
- [`ordering.txt`](results/ordering.txt): A list showing relationships
|
||||||
between modules where there are no loops as they actually exist, as
|
between modules where there are no loops as they actually exist, as
|
||||||
opposed to how they are desired as described above.
|
opposed to how they are desired as described above.
|
||||||
This file is committed to the repo, and is used by the [levelization
|
This file is committed to the repo, and is used by the [levelization
|
||||||
Github workflow](../../workflows/reusable-check-levelization.yml) to validate
|
Github workflow](../../workflows/check-levelization.yml) to validate
|
||||||
that nothing changed.
|
that nothing changed.
|
||||||
- [`levelization.yml`](../../workflows/reusable-check-levelization.yml)
|
- [`levelization.yml`](../../workflows/check-levelization.yml)
|
||||||
Github Actions workflow to test that levelization loops haven't
|
Github Actions workflow to test that levelization loops haven't
|
||||||
changed. Unfortunately, if changes are detected, it can't tell if
|
changed. Unfortunately, if changes are detected, it can't tell if
|
||||||
they are improvements or not, so if you have resolved any issues or
|
they are improvements or not, so if you have resolved any issues or
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ Loop: test.jtx test.unit_test
|
|||||||
Loop: xrpld.app xrpld.core
|
Loop: xrpld.app xrpld.core
|
||||||
xrpld.app > xrpld.core
|
xrpld.app > xrpld.core
|
||||||
|
|
||||||
|
Loop: xrpld.app xrpld.ledger
|
||||||
|
xrpld.app > xrpld.ledger
|
||||||
|
|
||||||
Loop: xrpld.app xrpld.overlay
|
Loop: xrpld.app xrpld.overlay
|
||||||
xrpld.overlay > xrpld.app
|
xrpld.overlay > xrpld.app
|
||||||
|
|
||||||
|
|||||||
@@ -2,10 +2,6 @@ libxrpl.basics > xrpl.basics
|
|||||||
libxrpl.crypto > xrpl.basics
|
libxrpl.crypto > xrpl.basics
|
||||||
libxrpl.json > xrpl.basics
|
libxrpl.json > xrpl.basics
|
||||||
libxrpl.json > xrpl.json
|
libxrpl.json > xrpl.json
|
||||||
libxrpl.ledger > xrpl.basics
|
|
||||||
libxrpl.ledger > xrpl.json
|
|
||||||
libxrpl.ledger > xrpl.ledger
|
|
||||||
libxrpl.ledger > xrpl.protocol
|
|
||||||
libxrpl.net > xrpl.basics
|
libxrpl.net > xrpl.basics
|
||||||
libxrpl.net > xrpl.net
|
libxrpl.net > xrpl.net
|
||||||
libxrpl.protocol > xrpl.basics
|
libxrpl.protocol > xrpl.basics
|
||||||
@@ -25,11 +21,11 @@ test.app > test.unit_test
|
|||||||
test.app > xrpl.basics
|
test.app > xrpl.basics
|
||||||
test.app > xrpld.app
|
test.app > xrpld.app
|
||||||
test.app > xrpld.core
|
test.app > xrpld.core
|
||||||
|
test.app > xrpld.ledger
|
||||||
test.app > xrpld.nodestore
|
test.app > xrpld.nodestore
|
||||||
test.app > xrpld.overlay
|
test.app > xrpld.overlay
|
||||||
test.app > xrpld.rpc
|
test.app > xrpld.rpc
|
||||||
test.app > xrpl.json
|
test.app > xrpl.json
|
||||||
test.app > xrpl.ledger
|
|
||||||
test.app > xrpl.protocol
|
test.app > xrpl.protocol
|
||||||
test.app > xrpl.resource
|
test.app > xrpl.resource
|
||||||
test.basics > test.jtx
|
test.basics > test.jtx
|
||||||
@@ -48,8 +44,8 @@ test.consensus > test.unit_test
|
|||||||
test.consensus > xrpl.basics
|
test.consensus > xrpl.basics
|
||||||
test.consensus > xrpld.app
|
test.consensus > xrpld.app
|
||||||
test.consensus > xrpld.consensus
|
test.consensus > xrpld.consensus
|
||||||
|
test.consensus > xrpld.ledger
|
||||||
test.consensus > xrpl.json
|
test.consensus > xrpl.json
|
||||||
test.consensus > xrpl.ledger
|
|
||||||
test.core > test.jtx
|
test.core > test.jtx
|
||||||
test.core > test.toplevel
|
test.core > test.toplevel
|
||||||
test.core > test.unit_test
|
test.core > test.unit_test
|
||||||
@@ -67,9 +63,9 @@ test.json > xrpl.json
|
|||||||
test.jtx > xrpl.basics
|
test.jtx > xrpl.basics
|
||||||
test.jtx > xrpld.app
|
test.jtx > xrpld.app
|
||||||
test.jtx > xrpld.core
|
test.jtx > xrpld.core
|
||||||
|
test.jtx > xrpld.ledger
|
||||||
test.jtx > xrpld.rpc
|
test.jtx > xrpld.rpc
|
||||||
test.jtx > xrpl.json
|
test.jtx > xrpl.json
|
||||||
test.jtx > xrpl.ledger
|
|
||||||
test.jtx > xrpl.net
|
test.jtx > xrpl.net
|
||||||
test.jtx > xrpl.protocol
|
test.jtx > xrpl.protocol
|
||||||
test.jtx > xrpl.resource
|
test.jtx > xrpl.resource
|
||||||
@@ -79,7 +75,7 @@ test.ledger > test.toplevel
|
|||||||
test.ledger > xrpl.basics
|
test.ledger > xrpl.basics
|
||||||
test.ledger > xrpld.app
|
test.ledger > xrpld.app
|
||||||
test.ledger > xrpld.core
|
test.ledger > xrpld.core
|
||||||
test.ledger > xrpl.ledger
|
test.ledger > xrpld.ledger
|
||||||
test.ledger > xrpl.protocol
|
test.ledger > xrpl.protocol
|
||||||
test.nodestore > test.jtx
|
test.nodestore > test.jtx
|
||||||
test.nodestore > test.toplevel
|
test.nodestore > test.toplevel
|
||||||
@@ -93,7 +89,6 @@ test.overlay > test.toplevel
|
|||||||
test.overlay > test.unit_test
|
test.overlay > test.unit_test
|
||||||
test.overlay > xrpl.basics
|
test.overlay > xrpl.basics
|
||||||
test.overlay > xrpld.app
|
test.overlay > xrpld.app
|
||||||
test.overlay > xrpld.nodestore
|
|
||||||
test.overlay > xrpld.overlay
|
test.overlay > xrpld.overlay
|
||||||
test.overlay > xrpld.peerfinder
|
test.overlay > xrpld.peerfinder
|
||||||
test.overlay > xrpld.shamap
|
test.overlay > xrpld.shamap
|
||||||
@@ -139,11 +134,7 @@ test.toplevel > test.csf
|
|||||||
test.toplevel > xrpl.json
|
test.toplevel > xrpl.json
|
||||||
test.unit_test > xrpl.basics
|
test.unit_test > xrpl.basics
|
||||||
tests.libxrpl > xrpl.basics
|
tests.libxrpl > xrpl.basics
|
||||||
tests.libxrpl > xrpl.json
|
|
||||||
tests.libxrpl > xrpl.net
|
|
||||||
xrpl.json > xrpl.basics
|
xrpl.json > xrpl.basics
|
||||||
xrpl.ledger > xrpl.basics
|
|
||||||
xrpl.ledger > xrpl.protocol
|
|
||||||
xrpl.net > xrpl.basics
|
xrpl.net > xrpl.basics
|
||||||
xrpl.protocol > xrpl.basics
|
xrpl.protocol > xrpl.basics
|
||||||
xrpl.protocol > xrpl.json
|
xrpl.protocol > xrpl.json
|
||||||
@@ -160,7 +151,6 @@ xrpld.app > xrpld.consensus
|
|||||||
xrpld.app > xrpld.nodestore
|
xrpld.app > xrpld.nodestore
|
||||||
xrpld.app > xrpld.perflog
|
xrpld.app > xrpld.perflog
|
||||||
xrpld.app > xrpl.json
|
xrpld.app > xrpl.json
|
||||||
xrpld.app > xrpl.ledger
|
|
||||||
xrpld.app > xrpl.net
|
xrpld.app > xrpl.net
|
||||||
xrpld.app > xrpl.protocol
|
xrpld.app > xrpl.protocol
|
||||||
xrpld.app > xrpl.resource
|
xrpld.app > xrpl.resource
|
||||||
@@ -173,6 +163,9 @@ xrpld.core > xrpl.basics
|
|||||||
xrpld.core > xrpl.json
|
xrpld.core > xrpl.json
|
||||||
xrpld.core > xrpl.net
|
xrpld.core > xrpl.net
|
||||||
xrpld.core > xrpl.protocol
|
xrpld.core > xrpl.protocol
|
||||||
|
xrpld.ledger > xrpl.basics
|
||||||
|
xrpld.ledger > xrpl.json
|
||||||
|
xrpld.ledger > xrpl.protocol
|
||||||
xrpld.nodestore > xrpl.basics
|
xrpld.nodestore > xrpl.basics
|
||||||
xrpld.nodestore > xrpld.core
|
xrpld.nodestore > xrpld.core
|
||||||
xrpld.nodestore > xrpld.unity
|
xrpld.nodestore > xrpld.unity
|
||||||
@@ -193,9 +186,9 @@ xrpld.perflog > xrpl.basics
|
|||||||
xrpld.perflog > xrpl.json
|
xrpld.perflog > xrpl.json
|
||||||
xrpld.rpc > xrpl.basics
|
xrpld.rpc > xrpl.basics
|
||||||
xrpld.rpc > xrpld.core
|
xrpld.rpc > xrpld.core
|
||||||
|
xrpld.rpc > xrpld.ledger
|
||||||
xrpld.rpc > xrpld.nodestore
|
xrpld.rpc > xrpld.nodestore
|
||||||
xrpld.rpc > xrpl.json
|
xrpld.rpc > xrpl.json
|
||||||
xrpld.rpc > xrpl.ledger
|
|
||||||
xrpld.rpc > xrpl.net
|
xrpld.rpc > xrpl.net
|
||||||
xrpld.rpc > xrpl.protocol
|
xrpld.rpc > xrpl.protocol
|
||||||
xrpld.rpc > xrpl.resource
|
xrpld.rpc > xrpl.resource
|
||||||
|
|||||||
20
.github/scripts/strategy-matrix/generate.py
vendored
20
.github/scripts/strategy-matrix/generate.py
vendored
@@ -45,7 +45,7 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
|
|||||||
# Only generate a subset of configurations in PRs.
|
# Only generate a subset of configurations in PRs.
|
||||||
if not all:
|
if not all:
|
||||||
# Debian:
|
# Debian:
|
||||||
# - Bookworm using GCC 13: Release and Unity on linux/amd64, set
|
# - Bookworm using GCC 13: Release and Unity on linux/arm64, set
|
||||||
# the reference fee to 500.
|
# the reference fee to 500.
|
||||||
# - Bookworm using GCC 15: Debug and no Unity on linux/amd64, enable
|
# - Bookworm using GCC 15: Debug and no Unity on linux/amd64, enable
|
||||||
# code coverage (which will be done below).
|
# code coverage (which will be done below).
|
||||||
@@ -57,7 +57,7 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
|
|||||||
if os['distro_name'] == 'debian':
|
if os['distro_name'] == 'debian':
|
||||||
skip = True
|
skip = True
|
||||||
if os['distro_version'] == 'bookworm':
|
if os['distro_version'] == 'bookworm':
|
||||||
if f'{os['compiler_name']}-{os['compiler_version']}' == 'gcc-13' and build_type == 'Release' and '-Dunity=ON' in cmake_args and architecture['platform'] == 'linux/amd64':
|
if f'{os['compiler_name']}-{os['compiler_version']}' == 'gcc-13' and build_type == 'Release' and '-Dunity=ON' in cmake_args and architecture['platform'] == 'linux/arm64':
|
||||||
cmake_args = f'-DUNIT_TEST_REFERENCE_FEE=500 {cmake_args}'
|
cmake_args = f'-DUNIT_TEST_REFERENCE_FEE=500 {cmake_args}'
|
||||||
skip = False
|
skip = False
|
||||||
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':
|
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':
|
||||||
@@ -74,14 +74,14 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
# RHEL:
|
# RHEL:
|
||||||
# - 9 using GCC 12: Debug and Unity on linux/amd64.
|
# - 9.4 using GCC 12: Debug and Unity on linux/amd64.
|
||||||
# - 10 using Clang: Release and no Unity on linux/amd64.
|
# - 9.6 using Clang: Release and no Unity on linux/amd64.
|
||||||
if os['distro_name'] == 'rhel':
|
if os['distro_name'] == 'rhel':
|
||||||
skip = True
|
skip = True
|
||||||
if os['distro_version'] == '9':
|
if os['distro_version'] == '9.4':
|
||||||
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':
|
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
|
skip = False
|
||||||
elif os['distro_version'] == '10':
|
elif os['distro_version'] == '9.6':
|
||||||
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':
|
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
|
skip = False
|
||||||
if skip:
|
if skip:
|
||||||
@@ -130,14 +130,16 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
|
|||||||
if os['distro_name'] == 'rhel' and architecture['platform'] == 'linux/arm64':
|
if os['distro_name'] == 'rhel' and architecture['platform'] == 'linux/arm64':
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# We skip all clang 20+ on arm64 due to Boost build error.
|
# We skip all clang-20 on arm64 due to boost 1.86 build error
|
||||||
if f'{os['compiler_name']}-{os['compiler_version']}' in ['clang-20', 'clang-21'] and architecture['platform'] == 'linux/arm64':
|
if f'{os['compiler_name']}-{os['compiler_version']}' == 'clang-20' and architecture['platform'] == 'linux/arm64':
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Enable code coverage for Debian Bookworm using GCC 15 in Debug and no
|
# Enable code coverage for Debian Bookworm using GCC 15 in Debug and no
|
||||||
# Unity on linux/amd64
|
# 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':
|
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_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
|
# Generate a unique name for the configuration, e.g. macos-arm64-debug
|
||||||
# or debian-bookworm-gcc-12-amd64-release-unity.
|
# or debian-bookworm-gcc-12-amd64-release-unity.
|
||||||
@@ -160,7 +162,7 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
|
|||||||
'config_name': config_name,
|
'config_name': config_name,
|
||||||
'cmake_args': cmake_args,
|
'cmake_args': cmake_args,
|
||||||
'cmake_target': cmake_target,
|
'cmake_target': cmake_target,
|
||||||
'build_only': build_only,
|
'build_only': 'true' if build_only else 'false',
|
||||||
'build_type': build_type,
|
'build_type': build_type,
|
||||||
'os': os,
|
'os': os,
|
||||||
'architecture': architecture,
|
'architecture': architecture,
|
||||||
|
|||||||
150
.github/scripts/strategy-matrix/linux.json
vendored
150
.github/scripts/strategy-matrix/linux.json
vendored
@@ -14,197 +14,139 @@
|
|||||||
"distro_name": "debian",
|
"distro_name": "debian",
|
||||||
"distro_version": "bookworm",
|
"distro_version": "bookworm",
|
||||||
"compiler_name": "gcc",
|
"compiler_name": "gcc",
|
||||||
"compiler_version": "12",
|
"compiler_version": "12"
|
||||||
"image_sha": "0525eae"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"distro_name": "debian",
|
"distro_name": "debian",
|
||||||
"distro_version": "bookworm",
|
"distro_version": "bookworm",
|
||||||
"compiler_name": "gcc",
|
"compiler_name": "gcc",
|
||||||
"compiler_version": "13",
|
"compiler_version": "13"
|
||||||
"image_sha": "0525eae"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"distro_name": "debian",
|
"distro_name": "debian",
|
||||||
"distro_version": "bookworm",
|
"distro_version": "bookworm",
|
||||||
"compiler_name": "gcc",
|
"compiler_name": "gcc",
|
||||||
"compiler_version": "14",
|
"compiler_version": "14"
|
||||||
"image_sha": "0525eae"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"distro_name": "debian",
|
"distro_name": "debian",
|
||||||
"distro_version": "bookworm",
|
"distro_version": "bookworm",
|
||||||
"compiler_name": "gcc",
|
"compiler_name": "gcc",
|
||||||
"compiler_version": "15",
|
"compiler_version": "15"
|
||||||
"image_sha": "0525eae"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"distro_name": "debian",
|
"distro_name": "debian",
|
||||||
"distro_version": "bookworm",
|
"distro_version": "bookworm",
|
||||||
"compiler_name": "clang",
|
"compiler_name": "clang",
|
||||||
"compiler_version": "16",
|
"compiler_version": "16"
|
||||||
"image_sha": "0525eae"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"distro_name": "debian",
|
"distro_name": "debian",
|
||||||
"distro_version": "bookworm",
|
"distro_version": "bookworm",
|
||||||
"compiler_name": "clang",
|
"compiler_name": "clang",
|
||||||
"compiler_version": "17",
|
"compiler_version": "17"
|
||||||
"image_sha": "0525eae"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"distro_name": "debian",
|
"distro_name": "debian",
|
||||||
"distro_version": "bookworm",
|
"distro_version": "bookworm",
|
||||||
"compiler_name": "clang",
|
"compiler_name": "clang",
|
||||||
"compiler_version": "18",
|
"compiler_version": "18"
|
||||||
"image_sha": "0525eae"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"distro_name": "debian",
|
"distro_name": "debian",
|
||||||
"distro_version": "bookworm",
|
"distro_version": "bookworm",
|
||||||
"compiler_name": "clang",
|
"compiler_name": "clang",
|
||||||
"compiler_version": "19",
|
"compiler_version": "19"
|
||||||
"image_sha": "0525eae"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"distro_name": "debian",
|
"distro_name": "debian",
|
||||||
"distro_version": "bookworm",
|
"distro_version": "bookworm",
|
||||||
"compiler_name": "clang",
|
"compiler_name": "clang",
|
||||||
"compiler_version": "20",
|
"compiler_version": "20"
|
||||||
"image_sha": "0525eae"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"distro_name": "debian",
|
"distro_name": "rhel",
|
||||||
"distro_version": "trixie",
|
"distro_version": "9.4",
|
||||||
"compiler_name": "gcc",
|
"compiler_name": "gcc",
|
||||||
"compiler_version": "14",
|
"compiler_version": "12"
|
||||||
"image_sha": "0525eae"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"distro_name": "debian",
|
"distro_name": "rhel",
|
||||||
"distro_version": "trixie",
|
"distro_version": "9.4",
|
||||||
"compiler_name": "gcc",
|
"compiler_name": "gcc",
|
||||||
"compiler_version": "15",
|
"compiler_version": "13"
|
||||||
"image_sha": "0525eae"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"distro_name": "debian",
|
"distro_name": "rhel",
|
||||||
"distro_version": "trixie",
|
"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",
|
||||||
"compiler_name": "clang",
|
"compiler_name": "clang",
|
||||||
"compiler_version": "20",
|
"compiler_version": "any"
|
||||||
"image_sha": "0525eae"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"distro_name": "debian",
|
"distro_name": "rhel",
|
||||||
"distro_version": "trixie",
|
"distro_version": "9.6",
|
||||||
"compiler_name": "clang",
|
"compiler_name": "clang",
|
||||||
"compiler_version": "21",
|
"compiler_version": "any"
|
||||||
"image_sha": "0525eae"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"distro_name": "rhel",
|
|
||||||
"distro_version": "8",
|
|
||||||
"compiler_name": "gcc",
|
|
||||||
"compiler_version": "14",
|
|
||||||
"image_sha": "e1782cd"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"distro_name": "rhel",
|
|
||||||
"distro_version": "8",
|
|
||||||
"compiler_name": "clang",
|
|
||||||
"compiler_version": "any",
|
|
||||||
"image_sha": "e1782cd"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"distro_name": "rhel",
|
|
||||||
"distro_version": "9",
|
|
||||||
"compiler_name": "gcc",
|
|
||||||
"compiler_version": "12",
|
|
||||||
"image_sha": "e1782cd"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"distro_name": "rhel",
|
|
||||||
"distro_version": "9",
|
|
||||||
"compiler_name": "gcc",
|
|
||||||
"compiler_version": "13",
|
|
||||||
"image_sha": "e1782cd"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"distro_name": "rhel",
|
|
||||||
"distro_version": "9",
|
|
||||||
"compiler_name": "gcc",
|
|
||||||
"compiler_version": "14",
|
|
||||||
"image_sha": "e1782cd"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"distro_name": "rhel",
|
|
||||||
"distro_version": "9",
|
|
||||||
"compiler_name": "clang",
|
|
||||||
"compiler_version": "any",
|
|
||||||
"image_sha": "e1782cd"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"distro_name": "rhel",
|
|
||||||
"distro_version": "10",
|
|
||||||
"compiler_name": "gcc",
|
|
||||||
"compiler_version": "14",
|
|
||||||
"image_sha": "e1782cd"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"distro_name": "rhel",
|
|
||||||
"distro_version": "10",
|
|
||||||
"compiler_name": "clang",
|
|
||||||
"compiler_version": "any",
|
|
||||||
"image_sha": "e1782cd"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"distro_name": "ubuntu",
|
"distro_name": "ubuntu",
|
||||||
"distro_version": "jammy",
|
"distro_version": "jammy",
|
||||||
"compiler_name": "gcc",
|
"compiler_name": "gcc",
|
||||||
"compiler_version": "12",
|
"compiler_version": "12"
|
||||||
"image_sha": "e1782cd"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"distro_name": "ubuntu",
|
"distro_name": "ubuntu",
|
||||||
"distro_version": "noble",
|
"distro_version": "noble",
|
||||||
"compiler_name": "gcc",
|
"compiler_name": "gcc",
|
||||||
"compiler_version": "13",
|
"compiler_version": "13"
|
||||||
"image_sha": "e1782cd"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"distro_name": "ubuntu",
|
"distro_name": "ubuntu",
|
||||||
"distro_version": "noble",
|
"distro_version": "noble",
|
||||||
"compiler_name": "gcc",
|
"compiler_name": "gcc",
|
||||||
"compiler_version": "14",
|
"compiler_version": "14"
|
||||||
"image_sha": "e1782cd"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"distro_name": "ubuntu",
|
"distro_name": "ubuntu",
|
||||||
"distro_version": "noble",
|
"distro_version": "noble",
|
||||||
"compiler_name": "clang",
|
"compiler_name": "clang",
|
||||||
"compiler_version": "16",
|
"compiler_version": "16"
|
||||||
"image_sha": "e1782cd"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"distro_name": "ubuntu",
|
"distro_name": "ubuntu",
|
||||||
"distro_version": "noble",
|
"distro_version": "noble",
|
||||||
"compiler_name": "clang",
|
"compiler_name": "clang",
|
||||||
"compiler_version": "17",
|
"compiler_version": "17"
|
||||||
"image_sha": "e1782cd"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"distro_name": "ubuntu",
|
"distro_name": "ubuntu",
|
||||||
"distro_version": "noble",
|
"distro_version": "noble",
|
||||||
"compiler_name": "clang",
|
"compiler_name": "clang",
|
||||||
"compiler_version": "18",
|
"compiler_version": "18"
|
||||||
"image_sha": "e1782cd"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"distro_name": "ubuntu",
|
"distro_name": "ubuntu",
|
||||||
"distro_version": "noble",
|
"distro_version": "noble",
|
||||||
"compiler_name": "clang",
|
"compiler_name": "clang",
|
||||||
"compiler_version": "19",
|
"compiler_version": "19"
|
||||||
"image_sha": "e1782cd"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"build_type": ["Debug", "Release"],
|
"build_type": ["Debug", "Release"],
|
||||||
|
|||||||
3
.github/scripts/strategy-matrix/macos.json
vendored
3
.github/scripts/strategy-matrix/macos.json
vendored
@@ -10,8 +10,7 @@
|
|||||||
"distro_name": "macos",
|
"distro_name": "macos",
|
||||||
"distro_version": "",
|
"distro_version": "",
|
||||||
"compiler_name": "",
|
"compiler_name": "",
|
||||||
"compiler_version": "",
|
"compiler_version": ""
|
||||||
"image_sha": ""
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"build_type": ["Debug", "Release"],
|
"build_type": ["Debug", "Release"],
|
||||||
|
|||||||
5
.github/scripts/strategy-matrix/windows.json
vendored
5
.github/scripts/strategy-matrix/windows.json
vendored
@@ -2,7 +2,7 @@
|
|||||||
"architecture": [
|
"architecture": [
|
||||||
{
|
{
|
||||||
"platform": "windows/amd64",
|
"platform": "windows/amd64",
|
||||||
"runner": ["self-hosted", "Windows", "devbox"]
|
"runner": ["windows-latest"]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"os": [
|
"os": [
|
||||||
@@ -10,8 +10,7 @@
|
|||||||
"distro_name": "windows",
|
"distro_name": "windows",
|
||||||
"distro_version": "",
|
"distro_version": "",
|
||||||
"compiler_name": "",
|
"compiler_name": "",
|
||||||
"compiler_version": "",
|
"compiler_version": ""
|
||||||
"image_sha": ""
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"build_type": ["Debug", "Release"],
|
"build_type": ["Debug", "Release"],
|
||||||
|
|||||||
146
.github/workflows/build-test.yml
vendored
Normal file
146
.github/workflows/build-test.yml
vendored
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
# This workflow builds and tests the binary for various configurations.
|
||||||
|
name: Build and test
|
||||||
|
|
||||||
|
# This workflow can only be triggered by other workflows. Note that the
|
||||||
|
# workflow_call event does not support the 'choice' input type, see
|
||||||
|
# https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax#onworkflow_callinputsinput_idtype,
|
||||||
|
# so we use 'string' instead.
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
build_dir:
|
||||||
|
description: "The directory where to build."
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
default: ".build"
|
||||||
|
dependencies_force_build:
|
||||||
|
description: "Force building of all dependencies."
|
||||||
|
required: false
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
dependencies_force_upload:
|
||||||
|
description: "Force uploading of all dependencies."
|
||||||
|
required: false
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
os:
|
||||||
|
description: 'The operating system to use for the build ("linux", "macos", "windows").'
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
strategy_matrix:
|
||||||
|
# TODO: Support additional strategies, e.g. "ubuntu" for generating all Ubuntu configurations.
|
||||||
|
description: 'The strategy matrix to use for generating the configurations ("minimal", "all").'
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
default: "minimal"
|
||||||
|
secrets:
|
||||||
|
codecov_token:
|
||||||
|
description: "The Codecov token to use for uploading coverage reports."
|
||||||
|
required: false
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}-${{ inputs.os }}
|
||||||
|
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:
|
||||||
|
os: ${{ inputs.os }}
|
||||||
|
strategy_matrix: ${{ inputs.strategy_matrix }}
|
||||||
|
|
||||||
|
# Build and test the binary.
|
||||||
|
build-test:
|
||||||
|
needs:
|
||||||
|
- generate-matrix
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}
|
||||||
|
runs-on: ${{ matrix.architecture.runner }}
|
||||||
|
container: ${{ inputs.os == 'linux' && format('ghcr.io/xrplf/ci/{0}-{1}:{2}-{3}', matrix.os.distro_name, matrix.os.distro_version, matrix.os.compiler_name, matrix.os.compiler_version) || null }}
|
||||||
|
steps:
|
||||||
|
- name: Check strategy matrix
|
||||||
|
run: |
|
||||||
|
echo 'Operating system distro name: ${{ matrix.os.distro_name }}'
|
||||||
|
echo 'Operating system distro version: ${{ matrix.os.distro_version }}'
|
||||||
|
echo 'Operating system compiler name: ${{ matrix.os.compiler_name }}'
|
||||||
|
echo 'Operating system compiler version: ${{ matrix.os.compiler_version }}'
|
||||||
|
echo 'Architecture platform: ${{ matrix.architecture.platform }}'
|
||||||
|
echo 'Architecture runner: ${{ toJson(matrix.architecture.runner) }}'
|
||||||
|
echo 'Build type: ${{ matrix.build_type }}'
|
||||||
|
echo 'Build only: ${{ matrix.build_only }}'
|
||||||
|
echo 'CMake arguments: ${{ matrix.cmake_args }}'
|
||||||
|
echo 'CMake target: ${{ matrix.cmake_target }}'
|
||||||
|
echo 'Config name: ${{ matrix.config_name }}'
|
||||||
|
|
||||||
|
- 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: Check configuration (Windows)
|
||||||
|
if: ${{ inputs.os == 'windows' }}
|
||||||
|
run: |
|
||||||
|
echo 'Checking environment variables.'
|
||||||
|
set
|
||||||
|
|
||||||
|
echo 'Checking CMake version.'
|
||||||
|
cmake --version
|
||||||
|
|
||||||
|
echo 'Checking Conan version.'
|
||||||
|
conan --version
|
||||||
|
- name: Check configuration (Linux and MacOS)
|
||||||
|
if: ${{ inputs.os == 'linux' || inputs.os == 'macos' }}
|
||||||
|
run: |
|
||||||
|
echo 'Checking path.'
|
||||||
|
echo ${PATH} | tr ':' '\n'
|
||||||
|
|
||||||
|
echo 'Checking environment variables.'
|
||||||
|
env | sort
|
||||||
|
|
||||||
|
echo 'Checking CMake version.'
|
||||||
|
cmake --version
|
||||||
|
|
||||||
|
echo 'Checking compiler version.'
|
||||||
|
${{ inputs.os == 'linux' && '${CC}' || 'clang' }} --version
|
||||||
|
|
||||||
|
echo 'Checking Conan version.'
|
||||||
|
conan --version
|
||||||
|
|
||||||
|
echo 'Checking Ninja version.'
|
||||||
|
ninja --version
|
||||||
|
|
||||||
|
echo 'Checking nproc version.'
|
||||||
|
nproc --version
|
||||||
|
|
||||||
|
- name: Setup Conan
|
||||||
|
uses: ./.github/actions/setup-conan
|
||||||
|
|
||||||
|
- name: Build dependencies
|
||||||
|
uses: ./.github/actions/build-deps
|
||||||
|
with:
|
||||||
|
build_dir: ${{ inputs.build_dir }}
|
||||||
|
build_type: ${{ matrix.build_type }}
|
||||||
|
force_build: ${{ inputs.dependencies_force_build }}
|
||||||
|
|
||||||
|
- name: Build and test binary
|
||||||
|
uses: ./.github/actions/build-test
|
||||||
|
with:
|
||||||
|
build_dir: ${{ inputs.build_dir }}
|
||||||
|
build_only: ${{ matrix.build_only }}
|
||||||
|
build_type: ${{ matrix.build_type }}
|
||||||
|
cmake_args: ${{ matrix.cmake_args }}
|
||||||
|
cmake_target: ${{ matrix.cmake_target }}
|
||||||
|
codecov_token: ${{ secrets.codecov_token }}
|
||||||
|
os: ${{ inputs.os }}
|
||||||
44
.github/workflows/check-format.yml
vendored
Normal file
44
.github/workflows/check-format.yml
vendored
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
# This workflow checks if the code is properly formatted.
|
||||||
|
name: Check format
|
||||||
|
|
||||||
|
# This workflow can only be triggered by other workflows.
|
||||||
|
on: workflow_call
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}-format
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
pre-commit:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container: ghcr.io/xrplf/ci/tools-rippled-pre-commit
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
|
- name: Prepare runner
|
||||||
|
uses: XRPLF/actions/.github/actions/prepare-runner@638e0dc11ea230f91bd26622fb542116bb5254d5
|
||||||
|
- name: Format code
|
||||||
|
run: pre-commit run --show-diff-on-failure --color=always --all-files
|
||||||
|
- name: Check for differences
|
||||||
|
env:
|
||||||
|
MESSAGE: |
|
||||||
|
One or more files did not conform to the formatting. Maybe you did
|
||||||
|
not run 'pre-commit' before committing, or your version of
|
||||||
|
'clang-format' or 'prettier' has an incompatibility with the ones
|
||||||
|
used here (see the "Check configuration" step above).
|
||||||
|
|
||||||
|
Run 'pre-commit run --all-files' in your repo, and then commit and
|
||||||
|
push the changes.
|
||||||
|
run: |
|
||||||
|
DIFF=$(git status --porcelain)
|
||||||
|
if [ -n "${DIFF}" ]; then
|
||||||
|
# Print the files that changed to give the contributor a hint about
|
||||||
|
# what to expect when running pre-commit on their own machine.
|
||||||
|
git status
|
||||||
|
echo "${MESSAGE}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
62
.github/workflows/check-missing-commits.yml
vendored
Normal file
62
.github/workflows/check-missing-commits.yml
vendored
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
# This workflow checks that all commits in the "master" branch are also in the
|
||||||
|
# "release" and "develop" branches, and that all commits in the "release" branch
|
||||||
|
# are also in the "develop" branch.
|
||||||
|
name: Check for missing commits
|
||||||
|
|
||||||
|
# This workflow can only be triggered by other workflows.
|
||||||
|
on: workflow_call
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}-missing-commits
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: Check for missing commits
|
||||||
|
env:
|
||||||
|
MESSAGE: |
|
||||||
|
|
||||||
|
If you are reading this, then the commits indicated above are missing
|
||||||
|
from the "develop" and/or "release" branch. Do a reverse-merge as soon
|
||||||
|
as possible. See CONTRIBUTING.md for instructions.
|
||||||
|
run: |
|
||||||
|
set -o pipefail
|
||||||
|
# Branches are ordered by how "canonical" they are. Every commit in one
|
||||||
|
# branch should be in all the branches behind it.
|
||||||
|
order=(master release develop)
|
||||||
|
branches=()
|
||||||
|
for branch in "${order[@]}"; do
|
||||||
|
# Check that the branches exist so that this job will work on forked
|
||||||
|
# repos, which don't necessarily have master and release branches.
|
||||||
|
echo "Checking if ${branch} exists."
|
||||||
|
if git ls-remote --exit-code --heads origin \
|
||||||
|
refs/heads/${branch} > /dev/null; then
|
||||||
|
branches+=(origin/${branch})
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
prior=()
|
||||||
|
for branch in "${branches[@]}"; do
|
||||||
|
if [[ ${#prior[@]} -ne 0 ]]; then
|
||||||
|
echo "Checking ${prior[@]} for commits missing from ${branch}."
|
||||||
|
git log --oneline --no-merges "${prior[@]}" \
|
||||||
|
^$branch | tee -a "missing-commits.txt"
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
prior+=("${branch}")
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ $(cat missing-commits.txt | wc -l) -ne 0 ]]; then
|
||||||
|
echo "${MESSAGE}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
@@ -40,52 +40,47 @@ jobs:
|
|||||||
upload:
|
upload:
|
||||||
if: ${{ github.event.pull_request.head.repo.full_name == github.repository }}
|
if: ${{ github.event.pull_request.head.repo.full_name == github.repository }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container: ghcr.io/xrplf/ci/ubuntu-noble:gcc-13-sha-5dd7158
|
container: ghcr.io/xrplf/ci/ubuntu-noble:gcc-13
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
- name: Generate outputs
|
- name: Generate outputs
|
||||||
id: generate
|
id: generate
|
||||||
env:
|
|
||||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
|
||||||
run: |
|
run: |
|
||||||
echo 'Generating user and channel.'
|
echo 'Generating user and channel.'
|
||||||
echo "user=clio" >> "${GITHUB_OUTPUT}"
|
echo "user=clio" >> "${GITHUB_OUTPUT}"
|
||||||
echo "channel=pr_${PR_NUMBER}" >> "${GITHUB_OUTPUT}"
|
echo "channel=pr_${{ github.event.pull_request.number }}" >> "${GITHUB_OUTPUT}"
|
||||||
echo 'Extracting version.'
|
echo 'Extracting version.'
|
||||||
echo "version=$(cat src/libxrpl/protocol/BuildInfo.cpp | grep "versionString =" | awk -F '"' '{print $2}')" >> "${GITHUB_OUTPUT}"
|
echo "version=$(cat src/libxrpl/protocol/BuildInfo.cpp | grep "versionString =" | awk -F '"' '{print $2}')" >> "${GITHUB_OUTPUT}"
|
||||||
- name: Calculate conan reference
|
- name: Calculate conan reference
|
||||||
id: conan_ref
|
id: conan_ref
|
||||||
run: |
|
run: |
|
||||||
echo "conan_ref=${{ steps.generate.outputs.version }}@${{ steps.generate.outputs.user }}/${{ steps.generate.outputs.channel }}" >> "${GITHUB_OUTPUT}"
|
echo "conan_ref=${{ steps.generate.outputs.version }}@${{ steps.generate.outputs.user }}/${{ steps.generate.outputs.channel }}" >> "${GITHUB_OUTPUT}"
|
||||||
|
|
||||||
- name: Set up Conan
|
- name: Set up Conan
|
||||||
uses: ./.github/actions/setup-conan
|
uses: ./.github/actions/setup-conan
|
||||||
with:
|
with:
|
||||||
conan_remote_name: ${{ inputs.conan_remote_name }}
|
conan_remote_name: ${{ inputs.conan_remote_name }}
|
||||||
conan_remote_url: ${{ inputs.conan_remote_url }}
|
conan_remote_url: ${{ inputs.conan_remote_url }}
|
||||||
|
|
||||||
- name: Log into Conan remote
|
- name: Log into Conan remote
|
||||||
env:
|
run: conan remote login ${{ inputs.conan_remote_name }} "${{ secrets.conan_remote_username }}" --password "${{ secrets.conan_remote_password }}"
|
||||||
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
|
- name: Upload package
|
||||||
env:
|
|
||||||
CONAN_REMOTE_NAME: ${{ inputs.conan_remote_name }}
|
|
||||||
run: |
|
run: |
|
||||||
conan export --user=${{ steps.generate.outputs.user }} --channel=${{ steps.generate.outputs.channel }} .
|
conan export --user=${{ steps.generate.outputs.user }} --channel=${{ steps.generate.outputs.channel }} .
|
||||||
conan upload --confirm --check --remote="${CONAN_REMOTE_NAME}" xrpl/${{ steps.conan_ref.outputs.conan_ref }}
|
conan upload --confirm --check --remote=${{ inputs.conan_remote_name }} xrpl/${{ steps.conan_ref.outputs.conan_ref }}
|
||||||
outputs:
|
outputs:
|
||||||
conan_ref: ${{ steps.conan_ref.outputs.conan_ref }}
|
conan_ref: ${{ steps.conan_ref.outputs.conan_ref }}
|
||||||
|
|
||||||
notify:
|
notify:
|
||||||
needs: upload
|
needs: upload
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ secrets.clio_notify_token }}
|
||||||
steps:
|
steps:
|
||||||
- name: Notify Clio
|
- name: Notify Clio
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.clio_notify_token }}
|
|
||||||
PR_URL: ${{ github.event.pull_request.html_url }}
|
|
||||||
run: |
|
run: |
|
||||||
gh api --method POST -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" \
|
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" \
|
/repos/xrplf/clio/dispatches -f "event_type=check_libxrpl" \
|
||||||
-F "client_payload[conan_ref]=${{ needs.upload.outputs.conan_ref }}" \
|
-F "client_payload[conan_ref]=${{ needs.upload.outputs.conan_ref }}" \
|
||||||
-F "client_payload[pr_url]=${PR_URL}"
|
-F "client_payload[pr_url]=${{ github.event.pull_request.html_url }}"
|
||||||
36
.github/workflows/on-pr.yml
vendored
36
.github/workflows/on-pr.yml
vendored
@@ -50,20 +50,18 @@ jobs:
|
|||||||
files: |
|
files: |
|
||||||
# These paths are unique to `on-pr.yml`.
|
# These paths are unique to `on-pr.yml`.
|
||||||
.github/scripts/levelization/**
|
.github/scripts/levelization/**
|
||||||
.github/workflows/reusable-check-levelization.yml
|
.github/workflows/check-format.yml
|
||||||
.github/workflows/reusable-notify-clio.yml
|
.github/workflows/check-levelization.yml
|
||||||
|
.github/workflows/notify-clio.yml
|
||||||
.github/workflows/on-pr.yml
|
.github/workflows/on-pr.yml
|
||||||
|
.clang-format
|
||||||
|
.pre-commit-config.yaml
|
||||||
|
|
||||||
# Keep the paths below in sync with those in `on-trigger.yml`.
|
# Keep the paths below in sync with those in `on-trigger.yml`.
|
||||||
.github/actions/build-deps/**
|
.github/actions/build-deps/**
|
||||||
.github/actions/build-test/**
|
.github/actions/build-test/**
|
||||||
.github/actions/setup-conan/**
|
|
||||||
.github/scripts/strategy-matrix/**
|
.github/scripts/strategy-matrix/**
|
||||||
.github/workflows/reusable-build.yml
|
.github/workflows/build-test.yml
|
||||||
.github/workflows/reusable-build-test-config.yml
|
|
||||||
.github/workflows/reusable-build-test.yml
|
|
||||||
.github/workflows/reusable-strategy-matrix.yml
|
|
||||||
.github/workflows/reusable-test.yml
|
|
||||||
.codecov.yml
|
.codecov.yml
|
||||||
cmake/**
|
cmake/**
|
||||||
conan/**
|
conan/**
|
||||||
@@ -93,31 +91,34 @@ jobs:
|
|||||||
outputs:
|
outputs:
|
||||||
go: ${{ steps.go.outputs.go == 'true' }}
|
go: ${{ steps.go.outputs.go == 'true' }}
|
||||||
|
|
||||||
|
check-format:
|
||||||
|
needs: should-run
|
||||||
|
if: needs.should-run.outputs.go == 'true'
|
||||||
|
uses: ./.github/workflows/check-format.yml
|
||||||
|
|
||||||
check-levelization:
|
check-levelization:
|
||||||
needs: should-run
|
needs: should-run
|
||||||
if: ${{ needs.should-run.outputs.go == 'true' }}
|
if: needs.should-run.outputs.go == 'true'
|
||||||
uses: ./.github/workflows/reusable-check-levelization.yml
|
uses: ./.github/workflows/check-levelization.yml
|
||||||
|
|
||||||
build-test:
|
build-test:
|
||||||
needs: should-run
|
needs: should-run
|
||||||
if: ${{ needs.should-run.outputs.go == 'true' }}
|
if: needs.should-run.outputs.go == 'true'
|
||||||
uses: ./.github/workflows/reusable-build-test.yml
|
uses: ./.github/workflows/build-test.yml
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
matrix:
|
||||||
os: [linux, macos, windows]
|
os: [linux, macos, windows]
|
||||||
with:
|
with:
|
||||||
os: ${{ matrix.os }}
|
os: ${{ matrix.os }}
|
||||||
secrets:
|
secrets:
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
codecov_token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
|
|
||||||
notify-clio:
|
notify-clio:
|
||||||
needs:
|
needs:
|
||||||
- should-run
|
- should-run
|
||||||
- build-test
|
- build-test
|
||||||
# Only run when committing to a PR that targets a release branch or master.
|
if: needs.should-run.outputs.go == 'true'
|
||||||
if: ${{ github.repository == 'XRPLF/rippled' && needs.should-run.outputs.go == 'true' && (startsWith(github.base_ref, 'release') || github.base_ref == 'master') }}
|
uses: ./.github/workflows/notify-clio.yml
|
||||||
uses: ./.github/workflows/reusable-notify-clio.yml
|
|
||||||
secrets:
|
secrets:
|
||||||
clio_notify_token: ${{ secrets.CLIO_NOTIFY_TOKEN }}
|
clio_notify_token: ${{ secrets.CLIO_NOTIFY_TOKEN }}
|
||||||
conan_remote_username: ${{ secrets.CONAN_REMOTE_USERNAME }}
|
conan_remote_username: ${{ secrets.CONAN_REMOTE_USERNAME }}
|
||||||
@@ -127,6 +128,7 @@ jobs:
|
|||||||
if: failure() || cancelled()
|
if: failure() || cancelled()
|
||||||
needs:
|
needs:
|
||||||
- build-test
|
- build-test
|
||||||
|
- check-format
|
||||||
- check-levelization
|
- check-levelization
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
49
.github/workflows/on-trigger.yml
vendored
49
.github/workflows/on-trigger.yml
vendored
@@ -9,23 +9,20 @@ name: Trigger
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- "develop"
|
- develop
|
||||||
- "release*"
|
- release
|
||||||
- "master"
|
- master
|
||||||
paths:
|
paths:
|
||||||
# These paths are unique to `on-trigger.yml`.
|
# These paths are unique to `on-trigger.yml`.
|
||||||
|
- ".github/workflows/check-missing-commits.yml"
|
||||||
- ".github/workflows/on-trigger.yml"
|
- ".github/workflows/on-trigger.yml"
|
||||||
|
- ".github/workflows/publish-docs.yml"
|
||||||
|
|
||||||
# Keep the paths below in sync with those in `on-pr.yml`.
|
# Keep the paths below in sync with those in `on-pr.yml`.
|
||||||
- ".github/actions/build-deps/**"
|
- ".github/actions/build-deps/**"
|
||||||
- ".github/actions/build-test/**"
|
- ".github/actions/build-test/**"
|
||||||
- ".github/actions/setup-conan/**"
|
|
||||||
- ".github/scripts/strategy-matrix/**"
|
- ".github/scripts/strategy-matrix/**"
|
||||||
- ".github/workflows/reusable-build.yml"
|
- ".github/workflows/build-test.yml"
|
||||||
- ".github/workflows/reusable-build-test-config.yml"
|
|
||||||
- ".github/workflows/reusable-build-test.yml"
|
|
||||||
- ".github/workflows/reusable-strategy-matrix.yml"
|
|
||||||
- ".github/workflows/reusable-test.yml"
|
|
||||||
- ".codecov.yml"
|
- ".codecov.yml"
|
||||||
- "cmake/**"
|
- "cmake/**"
|
||||||
- "conan/**"
|
- "conan/**"
|
||||||
@@ -44,16 +41,25 @@ on:
|
|||||||
schedule:
|
schedule:
|
||||||
- cron: "32 6 * * 1-5"
|
- cron: "32 6 * * 1-5"
|
||||||
|
|
||||||
# Run when manually triggered via the GitHub UI or API.
|
# Run when manually triggered via the GitHub UI or API. If `force_upload` is
|
||||||
|
# true, then the dependencies that were missing (`force_rebuild` is false) or
|
||||||
|
# rebuilt (`force_rebuild` is true) will be uploaded, overwriting existing
|
||||||
|
# dependencies if needed.
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
dependencies_force_build:
|
||||||
|
description: "Force building of all dependencies."
|
||||||
|
required: false
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
dependencies_force_upload:
|
||||||
|
description: "Force uploading of all dependencies."
|
||||||
|
required: false
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
# When a PR is merged into the develop branch it will be assigned a unique
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
# 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
|
cancel-in-progress: true
|
||||||
|
|
||||||
defaults:
|
defaults:
|
||||||
@@ -61,14 +67,17 @@ defaults:
|
|||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
check-missing-commits:
|
||||||
|
if: ${{ github.event_name == 'push' && github.ref_type == 'branch' && contains(fromJSON('["develop", "release"]'), github.ref_name) }}
|
||||||
|
uses: ./.github/workflows/check-missing-commits.yml
|
||||||
|
|
||||||
build-test:
|
build-test:
|
||||||
uses: ./.github/workflows/reusable-build-test.yml
|
uses: ./.github/workflows/build-test.yml
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: ${{ github.event_name == 'merge_group' }}
|
|
||||||
matrix:
|
matrix:
|
||||||
os: [linux, macos, windows]
|
os: [linux, macos, windows]
|
||||||
with:
|
with:
|
||||||
os: ${{ matrix.os }}
|
os: ${{ matrix.os }}
|
||||||
strategy_matrix: ${{ github.event_name == 'schedule' && 'all' || 'minimal' }}
|
strategy_matrix: "minimal"
|
||||||
secrets:
|
secrets:
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
codecov_token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
|
|||||||
15
.github/workflows/pre-commit.yml
vendored
15
.github/workflows/pre-commit.yml
vendored
@@ -1,15 +0,0 @@
|
|||||||
name: Run pre-commit hooks
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
push:
|
|
||||||
branches: [develop, release, master]
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
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@34790936fae4c6c751f62ec8c06696f9c1a5753a
|
|
||||||
with:
|
|
||||||
runs_on: ubuntu-latest
|
|
||||||
container: '{ "image": "ghcr.io/xrplf/ci/tools-rippled-pre-commit:sha-a8c7be1" }'
|
|
||||||
70
.github/workflows/publish-docs.yml
vendored
70
.github/workflows/publish-docs.yml
vendored
@@ -4,17 +4,6 @@ name: Build and publish documentation
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
|
||||||
- "develop"
|
|
||||||
paths:
|
|
||||||
- ".github/workflows/publish-docs.yml"
|
|
||||||
- "*.md"
|
|
||||||
- "**/*.md"
|
|
||||||
- "docs/**"
|
|
||||||
- "include/**"
|
|
||||||
- "src/libxrpl/**"
|
|
||||||
- "src/xrpld/**"
|
|
||||||
pull_request:
|
|
||||||
paths:
|
paths:
|
||||||
- ".github/workflows/publish-docs.yml"
|
- ".github/workflows/publish-docs.yml"
|
||||||
- "*.md"
|
- "*.md"
|
||||||
@@ -33,30 +22,17 @@ defaults:
|
|||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
env:
|
env:
|
||||||
BUILD_DIR: build
|
BUILD_DIR: .build
|
||||||
# ubuntu-latest has only 2 CPUs for private repositories
|
|
||||||
# https://docs.github.com/en/actions/reference/runners/github-hosted-runners#standard-github-hosted-runners-for--private-repositories
|
|
||||||
NPROC_SUBTRACT: ${{ github.event.repository.visibility == 'public' && '2' || '1' }}
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
publish:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container: ghcr.io/xrplf/ci/tools-rippled-documentation:sha-a8c7be1
|
container: ghcr.io/xrplf/ci/tools-rippled-documentation
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
|
|
||||||
- name: Prepare runner
|
|
||||||
uses: XRPLF/actions/prepare-runner@90f11ee655d1687824fb8793db770477d52afbab
|
|
||||||
with:
|
|
||||||
enable_ccache: false
|
|
||||||
|
|
||||||
- name: Get number of processors
|
|
||||||
uses: XRPLF/actions/get-nproc@cf0433aa74563aead044a1e395610c96d65a37cf
|
|
||||||
id: nproc
|
|
||||||
with:
|
|
||||||
subtract: ${{ env.NPROC_SUBTRACT }}
|
|
||||||
|
|
||||||
- name: Check configuration
|
- name: Check configuration
|
||||||
run: |
|
run: |
|
||||||
echo 'Checking path.'
|
echo 'Checking path.'
|
||||||
@@ -70,33 +46,15 @@ jobs:
|
|||||||
|
|
||||||
echo 'Checking Doxygen version.'
|
echo 'Checking Doxygen version.'
|
||||||
doxygen --version
|
doxygen --version
|
||||||
|
|
||||||
- name: Build documentation
|
- name: Build documentation
|
||||||
env:
|
|
||||||
BUILD_NPROC: ${{ steps.nproc.outputs.nproc }}
|
|
||||||
run: |
|
run: |
|
||||||
mkdir -p "${BUILD_DIR}"
|
mkdir -p ${{ env.BUILD_DIR }}
|
||||||
cd "${BUILD_DIR}"
|
cd ${{ env.BUILD_DIR }}
|
||||||
cmake -Donly_docs=ON ..
|
cmake -Donly_docs=ON ..
|
||||||
cmake --build . --target docs --parallel ${BUILD_NPROC}
|
cmake --build . --target docs --parallel $(nproc)
|
||||||
|
- name: Publish documentation
|
||||||
- name: Create documentation artifact
|
if: ${{ github.ref_type == 'branch' && github.ref_name == github.event.repository.default_branch }}
|
||||||
if: ${{ github.event.repository.visibility == 'public' && github.event_name == 'push' }}
|
uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0
|
||||||
uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0
|
|
||||||
with:
|
with:
|
||||||
path: ${{ env.BUILD_DIR }}/docs/html
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
publish_dir: ${{ env.BUILD_DIR }}/docs/html
|
||||||
deploy:
|
|
||||||
if: ${{ github.repository == 'XRPLF/rippled' && github.event_name == 'push' }}
|
|
||||||
needs: build
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
pages: write
|
|
||||||
id-token: write
|
|
||||||
environment:
|
|
||||||
name: github-pages
|
|
||||||
url: ${{ steps.deploy.outputs.page_url }}
|
|
||||||
steps:
|
|
||||||
- name: Deploy to GitHub Pages
|
|
||||||
id: deploy
|
|
||||||
uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0
|
|
||||||
|
|||||||
213
.github/workflows/reusable-build-test-config.yml
vendored
213
.github/workflows/reusable-build-test-config.yml
vendored
@@ -1,213 +0,0 @@
|
|||||||
name: Build and test configuration
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
inputs:
|
|
||||||
build_dir:
|
|
||||||
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
|
|
||||||
required: true
|
|
||||||
|
|
||||||
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 configuration string (used for naming artifacts and such)."
|
|
||||||
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
|
|
||||||
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
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 (macOS and Windows)
|
|
||||||
if: ${{ runner.os == 'macOS' || runner.os == 'Windows' }}
|
|
||||||
uses: XRPLF/actions/.github/actions/cleanup-workspace@01b244d2718865d427b499822fbd3f15e7197fcc
|
|
||||||
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
|
||||||
|
|
||||||
- name: Prepare runner
|
|
||||||
uses: XRPLF/actions/prepare-runner@2cbf481018d930656e9276fcc20dc0e3a0be5b6d
|
|
||||||
with:
|
|
||||||
enable_ccache: ${{ inputs.ccache_enabled }}
|
|
||||||
|
|
||||||
- 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: ${{ github.repository == 'XRPLF/rippled' && 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 == 'XRPLF/rippled' && !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
|
|
||||||
58
.github/workflows/reusable-build-test.yml
vendored
58
.github/workflows/reusable-build-test.yml
vendored
@@ -1,58 +0,0 @@
|
|||||||
# This workflow builds and tests the binary for various configurations.
|
|
||||||
name: Build and test
|
|
||||||
|
|
||||||
# This workflow can only be triggered by other workflows. Note that the
|
|
||||||
# workflow_call event does not support the 'choice' input type, see
|
|
||||||
# https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax#onworkflow_callinputsinput_idtype,
|
|
||||||
# so we use 'string' instead.
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
inputs:
|
|
||||||
build_dir:
|
|
||||||
description: "The directory where to build."
|
|
||||||
required: false
|
|
||||||
type: string
|
|
||||||
default: ".build"
|
|
||||||
os:
|
|
||||||
description: 'The operating system to use for the build ("linux", "macos", "windows").'
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
strategy_matrix:
|
|
||||||
# TODO: Support additional strategies, e.g. "ubuntu" for generating all Ubuntu configurations.
|
|
||||||
description: 'The strategy matrix to use for generating the configurations ("minimal", "all").'
|
|
||||||
required: false
|
|
||||||
type: string
|
|
||||||
default: "minimal"
|
|
||||||
secrets:
|
|
||||||
CODECOV_TOKEN:
|
|
||||||
description: "The Codecov token to use for uploading coverage reports."
|
|
||||||
required: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
# Generate the strategy matrix to be used by the following job.
|
|
||||||
generate-matrix:
|
|
||||||
uses: ./.github/workflows/reusable-strategy-matrix.yml
|
|
||||||
with:
|
|
||||||
os: ${{ inputs.os }}
|
|
||||||
strategy_matrix: ${{ inputs.strategy_matrix }}
|
|
||||||
|
|
||||||
# Build and test the binary for each configuration.
|
|
||||||
build-test-config:
|
|
||||||
needs:
|
|
||||||
- generate-matrix
|
|
||||||
uses: ./.github/workflows/reusable-build-test-config.yml
|
|
||||||
strategy:
|
|
||||||
fail-fast: ${{ github.event_name == 'merge_group' }}
|
|
||||||
matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}
|
|
||||||
max-parallel: 10
|
|
||||||
with:
|
|
||||||
build_dir: ${{ inputs.build_dir }}
|
|
||||||
build_only: ${{ matrix.build_only }}
|
|
||||||
build_type: ${{ matrix.build_type }}
|
|
||||||
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-{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 }}
|
|
||||||
@@ -18,10 +18,6 @@ on:
|
|||||||
description: "The generated strategy matrix."
|
description: "The generated strategy matrix."
|
||||||
value: ${{ jobs.generate-matrix.outputs.matrix }}
|
value: ${{ jobs.generate-matrix.outputs.matrix }}
|
||||||
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
generate-matrix:
|
generate-matrix:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -39,7 +35,4 @@ jobs:
|
|||||||
- name: Generate strategy matrix
|
- name: Generate strategy matrix
|
||||||
working-directory: .github/scripts/strategy-matrix
|
working-directory: .github/scripts/strategy-matrix
|
||||||
id: generate
|
id: generate
|
||||||
env:
|
run: ./generate.py ${{ inputs.strategy_matrix == 'all' && '--all' || '' }} ${{ inputs.os != '' && format('--config={0}.json', inputs.os) || '' }} >> "${GITHUB_OUTPUT}"
|
||||||
GENERATE_CONFIG: ${{ inputs.os != '' && format('--config={0}.json', inputs.os) || '' }}
|
|
||||||
GENERATE_OPTION: ${{ inputs.strategy_matrix == 'all' && '--all' || '' }}
|
|
||||||
run: ./generate.py ${GENERATE_OPTION} ${GENERATE_CONFIG} >> "${GITHUB_OUTPUT}"
|
|
||||||
|
|||||||
60
.github/workflows/upload-conan-deps.yml
vendored
60
.github/workflows/upload-conan-deps.yml
vendored
@@ -24,34 +24,25 @@ on:
|
|||||||
branches: [develop]
|
branches: [develop]
|
||||||
paths:
|
paths:
|
||||||
- .github/workflows/upload-conan-deps.yml
|
- .github/workflows/upload-conan-deps.yml
|
||||||
|
|
||||||
- .github/workflows/reusable-strategy-matrix.yml
|
- .github/workflows/reusable-strategy-matrix.yml
|
||||||
|
|
||||||
- .github/actions/build-deps/action.yml
|
- .github/actions/build-deps/action.yml
|
||||||
- .github/actions/setup-conan/action.yml
|
|
||||||
- ".github/scripts/strategy-matrix/**"
|
- ".github/scripts/strategy-matrix/**"
|
||||||
|
|
||||||
- conanfile.py
|
- conanfile.py
|
||||||
- conan.lock
|
- conan.lock
|
||||||
|
|
||||||
env:
|
|
||||||
CONAN_REMOTE_NAME: xrplf
|
|
||||||
CONAN_REMOTE_URL: https://conan.ripplex.io
|
|
||||||
NPROC_SUBTRACT: 2
|
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
# Generate the strategy matrix to be used by the following job.
|
|
||||||
generate-matrix:
|
generate-matrix:
|
||||||
uses: ./.github/workflows/reusable-strategy-matrix.yml
|
uses: ./.github/workflows/reusable-strategy-matrix.yml
|
||||||
with:
|
with:
|
||||||
strategy_matrix: ${{ github.event_name == 'pull_request' && 'minimal' || 'all' }}
|
strategy_matrix: ${{ github.event_name == 'pull_request' && 'minimal' || 'all' }}
|
||||||
|
|
||||||
# Build and upload the dependencies for each configuration.
|
|
||||||
run-upload-conan-deps:
|
run-upload-conan-deps:
|
||||||
needs:
|
needs:
|
||||||
- generate-matrix
|
- generate-matrix
|
||||||
@@ -60,52 +51,33 @@ jobs:
|
|||||||
matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}
|
matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}
|
||||||
max-parallel: 10
|
max-parallel: 10
|
||||||
runs-on: ${{ matrix.architecture.runner }}
|
runs-on: ${{ matrix.architecture.runner }}
|
||||||
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 }}
|
container: ${{ contains(matrix.architecture.platform, 'linux') && format('ghcr.io/xrplf/ci/{0}-{1}:{2}-{3}', matrix.os.distro_name, matrix.os.distro_version, matrix.os.compiler_name, matrix.os.compiler_version) || null }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Cleanup workspace (macOS and Windows)
|
- name: Cleanup workspace
|
||||||
if: ${{ runner.os == 'macOS' || runner.os == 'Windows' }}
|
if: ${{ runner.os == 'macOS' }}
|
||||||
uses: XRPLF/actions/.github/actions/cleanup-workspace@01b244d2718865d427b499822fbd3f15e7197fcc
|
uses: XRPLF/actions/.github/actions/cleanup-workspace@3f044c7478548e3c32ff68980eeb36ece02b364e
|
||||||
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
|
||||||
|
|
||||||
|
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
- name: Prepare runner
|
- name: Prepare runner
|
||||||
uses: XRPLF/actions/prepare-runner@2cbf481018d930656e9276fcc20dc0e3a0be5b6d
|
uses: XRPLF/actions/.github/actions/prepare-runner@638e0dc11ea230f91bd26622fb542116bb5254d5
|
||||||
with:
|
with:
|
||||||
enable_ccache: false
|
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
|
- name: Setup Conan
|
||||||
uses: ./.github/actions/setup-conan
|
uses: ./.github/actions/setup-conan
|
||||||
with:
|
|
||||||
conan_remote_name: ${{ env.CONAN_REMOTE_NAME }}
|
|
||||||
conan_remote_url: ${{ env.CONAN_REMOTE_URL }}
|
|
||||||
|
|
||||||
- name: Build dependencies
|
- name: Build dependencies
|
||||||
uses: ./.github/actions/build-deps
|
uses: ./.github/actions/build-deps
|
||||||
with:
|
with:
|
||||||
build_dir: .build
|
build_dir: .build
|
||||||
build_nproc: ${{ steps.nproc.outputs.nproc }}
|
|
||||||
build_type: ${{ matrix.build_type }}
|
build_type: ${{ matrix.build_type }}
|
||||||
force_build: ${{ github.event_name == 'schedule' || github.event.inputs.force_source_build == 'true' }}
|
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
|
- name: Login to Conan
|
||||||
if: ${{ github.repository == 'XRPLF/rippled' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') }}
|
if: github.repository_owner == 'XRPLF' && github.event_name != 'pull_request'
|
||||||
run: conan remote login "${CONAN_REMOTE_NAME}" "${{ secrets.CONAN_REMOTE_USERNAME }}" --password "${{ secrets.CONAN_REMOTE_PASSWORD }}"
|
run: conan remote login -p ${{ secrets.CONAN_PASSWORD }} ${{ inputs.conan_remote_name }} ${{ secrets.CONAN_USERNAME }}
|
||||||
|
|
||||||
- name: Upload Conan packages
|
- name: Upload Conan packages
|
||||||
if: ${{ github.repository == 'XRPLF/rippled' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') }}
|
if: github.repository_owner == 'XRPLF' && github.event_name != 'pull_request' && github.event_name != 'schedule'
|
||||||
env:
|
run: conan upload "*" -r=${{ inputs.conan_remote_name }} --confirm ${{ github.event.inputs.force_upload == 'true' && '--force' || '' }}
|
||||||
FORCE_OPTION: ${{ github.event.inputs.force_upload == 'true' && '--force' || '' }}
|
|
||||||
run: conan upload "*" --remote="${CONAN_REMOTE_NAME}" --confirm ${FORCE_OPTION}
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ repos:
|
|||||||
hooks:
|
hooks:
|
||||||
- id: trailing-whitespace
|
- id: trailing-whitespace
|
||||||
- id: end-of-file-fixer
|
- id: end-of-file-fixer
|
||||||
|
- id: mixed-line-ending
|
||||||
- id: check-merge-conflict
|
- id: check-merge-conflict
|
||||||
args: [--assume-in-merge]
|
args: [--assume-in-merge]
|
||||||
|
|
||||||
@@ -29,10 +30,10 @@ repos:
|
|||||||
rev: 5ba47274f9b181bce26a5150a725577f3c336011 # frozen: v3.6.2
|
rev: 5ba47274f9b181bce26a5150a725577f3c336011 # frozen: v3.6.2
|
||||||
hooks:
|
hooks:
|
||||||
- id: prettier
|
- id: prettier
|
||||||
args: [--end-of-line=auto]
|
|
||||||
|
|
||||||
exclude: |
|
exclude: |
|
||||||
(?x)^(
|
(?x)^(
|
||||||
external/.*|
|
external/.*|
|
||||||
.github/scripts/levelization/results/.*\.txt
|
.github/scripts/levelization/results/.*\.txt|
|
||||||
|
conan\.lock
|
||||||
)$
|
)$
|
||||||
|
|||||||
@@ -79,40 +79,6 @@ This version is supported by all `rippled` versions. For WebSocket and HTTP JSON
|
|||||||
|
|
||||||
The [commandline](https://xrpl.org/docs/references/http-websocket-apis/api-conventions/request-formatting/#commandline-format) always uses the latest API version. The command line is intended for ad-hoc usage by humans, not programs or automated scripts. The command line is not meant for use in production code.
|
The [commandline](https://xrpl.org/docs/references/http-websocket-apis/api-conventions/request-formatting/#commandline-format) always uses the latest API version. The command line is intended for ad-hoc usage by humans, not programs or automated scripts. The command line is not meant for use in production code.
|
||||||
|
|
||||||
## XRP Ledger server version 3.1.3
|
|
||||||
|
|
||||||
### Bugfixes in 3.1.3
|
|
||||||
|
|
||||||
- Peer Crawler: The `port` field in `overlay.active[]` now consistently returns an integer instead of a string for outbound peers. [#6318](https://github.com/XRPLF/rippled/pull/6318)
|
|
||||||
|
|
||||||
## XRP Ledger server version 3.1.0
|
|
||||||
|
|
||||||
[Version 3.1.0](https://github.com/XRPLF/rippled/releases/tag/3.1.0) was released on Jan 27, 2026.
|
|
||||||
|
|
||||||
### Additions in 3.1.0
|
|
||||||
|
|
||||||
- `vault_info`: New RPC method to retrieve information about a specific vault (part of XLS-66 Lending Protocol). ([#6156](https://github.com/XRPLF/rippled/pull/6156))
|
|
||||||
|
|
||||||
## XRP Ledger server version 3.0.0
|
|
||||||
|
|
||||||
[Version 3.0.0](https://github.com/XRPLF/rippled/releases/tag/3.0.0) was released on Dec 9, 2025.
|
|
||||||
|
|
||||||
### Additions in 3.0.0
|
|
||||||
|
|
||||||
- `ledger_entry`: Supports all ledger entry types with dedicated parsers. ([#5237](https://github.com/XRPLF/rippled/pull/5237))
|
|
||||||
- `ledger_entry`: New error codes `entryNotFound` and `unexpectedLedgerType` for more specific error handling. ([#5237](https://github.com/XRPLF/rippled/pull/5237))
|
|
||||||
- `ledger_entry`: Improved error messages with more context (e.g., specifying which field is invalid or missing). ([#5237](https://github.com/XRPLF/rippled/pull/5237))
|
|
||||||
- `ledger_entry`: Assorted bug fixes in RPC processing. ([#5237](https://github.com/XRPLF/rippled/pull/5237))
|
|
||||||
- `simulate`: Supports additional metadata in the response. ([#5754](https://github.com/XRPLF/rippled/pull/5754))
|
|
||||||
|
|
||||||
## XRP Ledger server version 2.6.2
|
|
||||||
|
|
||||||
[Version 2.6.2](https://github.com/XRPLF/rippled/releases/tag/2.6.2) was released on Nov 19, 2025.
|
|
||||||
|
|
||||||
This release contains bug fixes only and no API changes.
|
|
||||||
|
|
||||||
## XRP Ledger server version 2.6.1
|
|
||||||
|
|
||||||
### Inconsistency: server_info - network_id
|
### Inconsistency: server_info - network_id
|
||||||
|
|
||||||
The `network_id` field was added in the `server_info` response in version 1.5.0 (2019), but it is not returned in [reporting mode](https://xrpl.org/rippled-server-modes.html#reporting-mode). However, use of reporting mode is now discouraged, in favor of using [Clio](https://github.com/XRPLF/clio) instead.
|
The `network_id` field was added in the `server_info` response in version 1.5.0 (2019), but it is not returned in [reporting mode](https://xrpl.org/rippled-server-modes.html#reporting-mode). However, use of reporting mode is now discouraged, in favor of using [Clio](https://github.com/XRPLF/clio) instead.
|
||||||
|
|||||||
62
BUILD.md
62
BUILD.md
@@ -39,12 +39,17 @@ found here](./docs/build/environment.md).
|
|||||||
|
|
||||||
- [Python 3.11](https://www.python.org/downloads/), or higher
|
- [Python 3.11](https://www.python.org/downloads/), or higher
|
||||||
- [Conan 2.17](https://conan.io/downloads.html)[^1], or higher
|
- [Conan 2.17](https://conan.io/downloads.html)[^1], or higher
|
||||||
- [CMake 3.22](https://cmake.org/download/), or higher
|
- [CMake 3.22](https://cmake.org/download/)[^2], or higher
|
||||||
|
|
||||||
[^1]:
|
[^1]:
|
||||||
It is possible to build with Conan 1.60+, but the instructions are
|
It is possible to build with Conan 1.60+, but the instructions are
|
||||||
significantly different, which is why we are not recommending it.
|
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.
|
`rippled` is written in the C++20 dialect and includes the `<concepts>` header.
|
||||||
The [minimum compiler versions][2] required are:
|
The [minimum compiler versions][2] required are:
|
||||||
|
|
||||||
@@ -127,7 +132,7 @@ higher index than the default Conan Center remote, so it is consulted first. You
|
|||||||
can do this by running:
|
can do this by running:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
conan remote add --index 0 xrplf https://conan.ripplex.io
|
conan remote add --index 0 xrplf "https://conan.ripplex.io"
|
||||||
```
|
```
|
||||||
|
|
||||||
Alternatively, you can pull the patched recipes into the repository and use them
|
Alternatively, you can pull the patched recipes into the repository and use them
|
||||||
@@ -277,6 +282,21 @@ 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
|
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
|
#### Clang workaround for grpc
|
||||||
|
|
||||||
If your compiler is clang, version 19 or later, or apple-clang, version 17 or
|
If your compiler is clang, version 19 or later, or apple-clang, version 17 or
|
||||||
@@ -459,24 +479,12 @@ It is implicitly used when running `conan` commands, you don't need to specify i
|
|||||||
|
|
||||||
You have to update this file every time you add a new dependency or change a revision or version of an existing dependency.
|
You have to update this file every time you add a new dependency or change a revision or version of an existing dependency.
|
||||||
|
|
||||||
> [!NOTE]
|
To do that, run the following command in the repository root:
|
||||||
> Conan uses local cache by default when creating a lockfile.
|
|
||||||
>
|
|
||||||
> To ensure, that lockfile creation works the same way on all developer machines, you should clear the local cache before creating a new lockfile.
|
|
||||||
|
|
||||||
To create a new lockfile, run the following commands in the repository root:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
conan remove '*' --confirm
|
|
||||||
rm conan.lock
|
|
||||||
# This ensure that xrplf remote is the first to be consulted
|
|
||||||
conan remote add --force --index 0 xrplf https://conan.ripplex.io
|
|
||||||
conan lock create . -o '&:jemalloc=True' -o '&:rocksdb=True'
|
conan lock create . -o '&:jemalloc=True' -o '&:rocksdb=True'
|
||||||
```
|
```
|
||||||
|
|
||||||
> [!NOTE]
|
|
||||||
> If some dependencies are exclusive for some OS, you may need to run the last command for them adding `--profile:all <PROFILE>`.
|
|
||||||
|
|
||||||
## Coverage report
|
## Coverage report
|
||||||
|
|
||||||
The coverage report is intended for developers using compilers GCC
|
The coverage report is intended for developers using compilers GCC
|
||||||
@@ -495,18 +503,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`
|
1. `rippled` binary built with instrumentation data, enabled by the `coverage`
|
||||||
option mentioned above
|
option mentioned above
|
||||||
2. completed one or more run of the unit tests, which populates coverage capture data
|
2. completed run of unit tests, which populates coverage capture data
|
||||||
3. completed run of the `gcovr` tool (which internally invokes either `gcov` or `llvm-cov`)
|
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
|
to assemble both instrumentation data and the coverage capture data into a coverage report
|
||||||
|
|
||||||
The last step of the above is automated into a single target `coverage`. The instrumented
|
The above steps are automated into a single target `coverage`. The instrumented
|
||||||
`rippled` binary can also be used for regular development or testing work, at
|
`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
|
the cost of extra disk space utilization and a small performance hit
|
||||||
(to store coverage capture data). Since `rippled` binary is simply a dependency of the
|
(to store coverage capture). In case of a spurious failure of unit tests, it is
|
||||||
coverage report target, it is possible to re-run the `coverage` target without
|
possible to re-run the `coverage` target without rebuilding the `rippled` binary
|
||||||
rebuilding the `rippled` binary. Note, running of the unit tests before the `coverage`
|
(since it is simply a dependency of the coverage report target). It is also possible
|
||||||
target is left to the developer. Each such run will append to the coverage data
|
to select only specific tests for the purpose of the coverage report, by setting
|
||||||
collected in the build directory.
|
the `coverage_test` variable in `cmake`
|
||||||
|
|
||||||
The default coverage report format is `html-details`, but the user
|
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`
|
can override it to any of the formats listed in `Builds/CMake/CodeCoverage.cmake`
|
||||||
@@ -515,6 +523,11 @@ 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
|
variable in `cmake`. The specific command line used to run the `gcovr` tool will be
|
||||||
displayed if the `CODE_COVERAGE_VERBOSE` variable is set.
|
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:
|
Example use with some cmake variables set:
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -573,11 +586,6 @@ After any updates or changes to dependencies, you may need to do the following:
|
|||||||
4. [Regenerate lockfile](#conan-lockfile).
|
4. [Regenerate lockfile](#conan-lockfile).
|
||||||
5. Re-run [conan install](#build-and-test).
|
5. Re-run [conan install](#build-and-test).
|
||||||
|
|
||||||
#### ERROR: Package not resolved
|
|
||||||
|
|
||||||
If you're seeing an error like `ERROR: Package 'snappy/1.1.10' not resolved: Unable to find 'snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1756234314.246' in remotes.`,
|
|
||||||
please add `xrplf` remote or re-run `conan export` for [patched recipes](#patched-recipes).
|
|
||||||
|
|
||||||
### `protobuf/port_def.inc` file not found
|
### `protobuf/port_def.inc` file not found
|
||||||
|
|
||||||
If `cmake --build .` results in an error due to a missing a protobuf file, then
|
If `cmake --build .` results in an error due to a missing a protobuf file, then
|
||||||
|
|||||||
@@ -527,17 +527,6 @@
|
|||||||
#
|
#
|
||||||
# The current default (which is subject to change) is 300 seconds.
|
# The current default (which is subject to change) is 300 seconds.
|
||||||
#
|
#
|
||||||
# verify_endpoints = <0 | 1>
|
|
||||||
#
|
|
||||||
# If set to 0, the server will skip validation of endpoint
|
|
||||||
# addresses received in TMEndpoints peer protocol messages,
|
|
||||||
# allowing addresses that are not publicly routable or have a
|
|
||||||
# port of 0. The default is 1 (verification enabled).
|
|
||||||
#
|
|
||||||
# WARNING: Disabling this option is a security risk and should
|
|
||||||
# only be used for local testing and debugging. Do not disable
|
|
||||||
# on mainnet.
|
|
||||||
#
|
|
||||||
#
|
#
|
||||||
# [transaction_queue] EXPERIMENTAL
|
# [transaction_queue] EXPERIMENTAL
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,3 +1,21 @@
|
|||||||
|
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_)
|
macro (exclude_from_default target_)
|
||||||
set_target_properties (${target_} PROPERTIES EXCLUDE_FROM_ALL ON)
|
set_target_properties (${target_} PROPERTIES EXCLUDE_FROM_ALL ON)
|
||||||
set_target_properties (${target_} PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD ON)
|
set_target_properties (${target_} PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD ON)
|
||||||
|
|||||||
@@ -104,14 +104,6 @@
|
|||||||
# 2025-08-28, Bronek Kozicki
|
# 2025-08-28, Bronek Kozicki
|
||||||
# - fix "At least one COMMAND must be given" CMake warning from policy CMP0175
|
# - fix "At least one COMMAND must be given" CMake warning from policy CMP0175
|
||||||
#
|
#
|
||||||
# 2025-09-03, Jingchen Wu
|
|
||||||
# - remove the unused function append_coverage_compiler_flags and append_coverage_compiler_flags_to_target
|
|
||||||
# - 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:
|
# USAGE:
|
||||||
#
|
#
|
||||||
# 1. Copy this file into your cmake modules path.
|
# 1. Copy this file into your cmake modules path.
|
||||||
@@ -120,8 +112,10 @@
|
|||||||
# using a CMake option() to enable it just optionally):
|
# using a CMake option() to enable it just optionally):
|
||||||
# include(CodeCoverage)
|
# include(CodeCoverage)
|
||||||
#
|
#
|
||||||
# 3. Append necessary compiler flags and linker flags for all supported source files:
|
# 3. Append necessary compiler flags for all supported source files:
|
||||||
# add_code_coverage_to_target(<target> <PRIVATE|PUBLIC|INTERFACE>)
|
# append_coverage_compiler_flags()
|
||||||
|
# Or for specific target:
|
||||||
|
# append_coverage_compiler_flags_to_target(YOUR_TARGET_NAME)
|
||||||
#
|
#
|
||||||
# 3.a (OPTIONAL) Set appropriate optimization flags, e.g. -O0, -O1 or -Og
|
# 3.a (OPTIONAL) Set appropriate optimization flags, e.g. -O0, -O1 or -Og
|
||||||
#
|
#
|
||||||
@@ -210,69 +204,67 @@ endforeach()
|
|||||||
|
|
||||||
set(COVERAGE_COMPILER_FLAGS "-g --coverage"
|
set(COVERAGE_COMPILER_FLAGS "-g --coverage"
|
||||||
CACHE INTERNAL "")
|
CACHE INTERNAL "")
|
||||||
|
|
||||||
set(COVERAGE_CXX_COMPILER_FLAGS "")
|
|
||||||
set(COVERAGE_C_COMPILER_FLAGS "")
|
|
||||||
set(COVERAGE_CXX_LINKER_FLAGS "")
|
|
||||||
set(COVERAGE_C_LINKER_FLAGS "")
|
|
||||||
|
|
||||||
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
|
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
|
||||||
include(CheckCXXCompilerFlag)
|
include(CheckCXXCompilerFlag)
|
||||||
include(CheckCCompilerFlag)
|
include(CheckCCompilerFlag)
|
||||||
include(CheckLinkerFlag)
|
|
||||||
|
|
||||||
set(COVERAGE_CXX_COMPILER_FLAGS ${COVERAGE_COMPILER_FLAGS})
|
|
||||||
set(COVERAGE_C_COMPILER_FLAGS ${COVERAGE_COMPILER_FLAGS})
|
|
||||||
set(COVERAGE_CXX_LINKER_FLAGS ${COVERAGE_COMPILER_FLAGS})
|
|
||||||
set(COVERAGE_C_LINKER_FLAGS ${COVERAGE_COMPILER_FLAGS})
|
|
||||||
|
|
||||||
check_cxx_compiler_flag(-fprofile-abs-path HAVE_cxx_fprofile_abs_path)
|
check_cxx_compiler_flag(-fprofile-abs-path HAVE_cxx_fprofile_abs_path)
|
||||||
if(HAVE_cxx_fprofile_abs_path)
|
if(HAVE_cxx_fprofile_abs_path)
|
||||||
set(COVERAGE_CXX_COMPILER_FLAGS "${COVERAGE_CXX_COMPILER_FLAGS} -fprofile-abs-path")
|
set(COVERAGE_CXX_COMPILER_FLAGS "${COVERAGE_COMPILER_FLAGS} -fprofile-abs-path")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
check_c_compiler_flag(-fprofile-abs-path HAVE_c_fprofile_abs_path)
|
check_c_compiler_flag(-fprofile-abs-path HAVE_c_fprofile_abs_path)
|
||||||
if(HAVE_c_fprofile_abs_path)
|
if(HAVE_c_fprofile_abs_path)
|
||||||
set(COVERAGE_C_COMPILER_FLAGS "${COVERAGE_C_COMPILER_FLAGS} -fprofile-abs-path")
|
set(COVERAGE_C_COMPILER_FLAGS "${COVERAGE_COMPILER_FLAGS} -fprofile-abs-path")
|
||||||
endif()
|
|
||||||
|
|
||||||
check_linker_flag(CXX -fprofile-abs-path HAVE_cxx_linker_fprofile_abs_path)
|
|
||||||
if(HAVE_cxx_linker_fprofile_abs_path)
|
|
||||||
set(COVERAGE_CXX_LINKER_FLAGS "${COVERAGE_CXX_LINKER_FLAGS} -fprofile-abs-path")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
check_linker_flag(C -fprofile-abs-path HAVE_c_linker_fprofile_abs_path)
|
|
||||||
if(HAVE_c_linker_fprofile_abs_path)
|
|
||||||
set(COVERAGE_C_LINKER_FLAGS "${COVERAGE_C_LINKER_FLAGS} -fprofile-abs-path")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
check_cxx_compiler_flag(-fprofile-update=atomic HAVE_cxx_fprofile_update)
|
check_cxx_compiler_flag(-fprofile-update=atomic HAVE_cxx_fprofile_update)
|
||||||
if(HAVE_cxx_fprofile_update)
|
if(HAVE_cxx_fprofile_update)
|
||||||
set(COVERAGE_CXX_COMPILER_FLAGS "${COVERAGE_CXX_COMPILER_FLAGS} -fprofile-update=atomic")
|
set(COVERAGE_CXX_COMPILER_FLAGS "${COVERAGE_COMPILER_FLAGS} -fprofile-update=atomic")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
check_c_compiler_flag(-fprofile-update=atomic HAVE_c_fprofile_update)
|
check_c_compiler_flag(-fprofile-update=atomic HAVE_c_fprofile_update)
|
||||||
if(HAVE_c_fprofile_update)
|
if(HAVE_c_fprofile_update)
|
||||||
set(COVERAGE_C_COMPILER_FLAGS "${COVERAGE_C_COMPILER_FLAGS} -fprofile-update=atomic")
|
set(COVERAGE_C_COMPILER_FLAGS "${COVERAGE_COMPILER_FLAGS} -fprofile-update=atomic")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
check_linker_flag(CXX -fprofile-update=atomic HAVE_cxx_linker_fprofile_update)
|
|
||||||
if(HAVE_cxx_linker_fprofile_update)
|
|
||||||
set(COVERAGE_CXX_LINKER_FLAGS "${COVERAGE_CXX_LINKER_FLAGS} -fprofile-update=atomic")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
check_linker_flag(C -fprofile-update=atomic HAVE_c_linker_fprofile_update)
|
|
||||||
if(HAVE_c_linker_fprofile_update)
|
|
||||||
set(COVERAGE_C_LINKER_FLAGS "${COVERAGE_C_LINKER_FLAGS} -fprofile-update=atomic")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_Fortran_FLAGS_COVERAGE
|
||||||
|
${COVERAGE_COMPILER_FLAGS}
|
||||||
|
CACHE STRING "Flags used by the Fortran compiler during coverage builds."
|
||||||
|
FORCE )
|
||||||
|
set(CMAKE_CXX_FLAGS_COVERAGE
|
||||||
|
${COVERAGE_COMPILER_FLAGS}
|
||||||
|
CACHE STRING "Flags used by the C++ compiler during coverage builds."
|
||||||
|
FORCE )
|
||||||
|
set(CMAKE_C_FLAGS_COVERAGE
|
||||||
|
${COVERAGE_COMPILER_FLAGS}
|
||||||
|
CACHE STRING "Flags used by the C compiler during coverage builds."
|
||||||
|
FORCE )
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS_COVERAGE
|
||||||
|
""
|
||||||
|
CACHE STRING "Flags used for linking binaries during coverage builds."
|
||||||
|
FORCE )
|
||||||
|
set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
|
||||||
|
""
|
||||||
|
CACHE STRING "Flags used by the shared libraries linker during coverage builds."
|
||||||
|
FORCE )
|
||||||
|
mark_as_advanced(
|
||||||
|
CMAKE_Fortran_FLAGS_COVERAGE
|
||||||
|
CMAKE_CXX_FLAGS_COVERAGE
|
||||||
|
CMAKE_C_FLAGS_COVERAGE
|
||||||
|
CMAKE_EXE_LINKER_FLAGS_COVERAGE
|
||||||
|
CMAKE_SHARED_LINKER_FLAGS_COVERAGE )
|
||||||
|
|
||||||
get_property(GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
get_property(GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||||
if(NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG))
|
if(NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG))
|
||||||
message(WARNING "Code coverage results with an optimised (non-Debug) build may be misleading")
|
message(WARNING "Code coverage results with an optimised (non-Debug) build may be misleading")
|
||||||
endif() # NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG)
|
endif() # NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG)
|
||||||
|
|
||||||
|
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
|
||||||
|
link_libraries(gcov)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Defines a target for running and collection code coverage information
|
# Defines a target for running and collection code coverage information
|
||||||
# Builds dependencies, runs the given executable and outputs reports.
|
# Builds dependencies, runs the given executable and outputs reports.
|
||||||
# NOTE! The executable should always have a ZERO as exit code otherwise
|
# NOTE! The executable should always have a ZERO as exit code otherwise
|
||||||
@@ -320,10 +312,6 @@ function(setup_target_for_coverage_gcovr)
|
|||||||
set(Coverage_FORMAT xml)
|
set(Coverage_FORMAT xml)
|
||||||
endif()
|
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)
|
if("--output" IN_LIST GCOVR_ADDITIONAL_ARGS)
|
||||||
message(FATAL_ERROR "Unsupported --output option detected in GCOVR_ADDITIONAL_ARGS! Aborting...")
|
message(FATAL_ERROR "Unsupported --output option detected in GCOVR_ADDITIONAL_ARGS! Aborting...")
|
||||||
else()
|
else()
|
||||||
@@ -405,18 +393,17 @@ function(setup_target_for_coverage_gcovr)
|
|||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
# Set up commands which will be run to generate coverage data
|
# Set up commands which will be run to generate coverage data
|
||||||
# If EXECUTABLE is not set, the user is expected to run the tests manually
|
# Run tests
|
||||||
# before running the coverage target NAME
|
set(GCOVR_EXEC_TESTS_CMD
|
||||||
if(DEFINED Coverage_EXECUTABLE)
|
${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
|
||||||
set(GCOVR_EXEC_TESTS_CMD
|
)
|
||||||
${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Create folder
|
# Create folder
|
||||||
if(DEFINED GCOVR_CREATE_FOLDER)
|
if(DEFINED GCOVR_CREATE_FOLDER)
|
||||||
set(GCOVR_FOLDER_CMD
|
set(GCOVR_FOLDER_CMD
|
||||||
${CMAKE_COMMAND} -E make_directory ${GCOVR_CREATE_FOLDER})
|
${CMAKE_COMMAND} -E make_directory ${GCOVR_CREATE_FOLDER})
|
||||||
|
else()
|
||||||
|
set(GCOVR_FOLDER_CMD echo) # dummy
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Running gcovr
|
# Running gcovr
|
||||||
@@ -433,13 +420,11 @@ function(setup_target_for_coverage_gcovr)
|
|||||||
if(CODE_COVERAGE_VERBOSE)
|
if(CODE_COVERAGE_VERBOSE)
|
||||||
message(STATUS "Executed command report")
|
message(STATUS "Executed command report")
|
||||||
|
|
||||||
if(NOT "${GCOVR_EXEC_TESTS_CMD}" STREQUAL "")
|
message(STATUS "Command to run tests: ")
|
||||||
message(STATUS "Command to run tests: ")
|
string(REPLACE ";" " " GCOVR_EXEC_TESTS_CMD_SPACED "${GCOVR_EXEC_TESTS_CMD}")
|
||||||
string(REPLACE ";" " " GCOVR_EXEC_TESTS_CMD_SPACED "${GCOVR_EXEC_TESTS_CMD}")
|
message(STATUS "${GCOVR_EXEC_TESTS_CMD_SPACED}")
|
||||||
message(STATUS "${GCOVR_EXEC_TESTS_CMD_SPACED}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT "${GCOVR_FOLDER_CMD}" STREQUAL "")
|
if(NOT GCOVR_FOLDER_CMD STREQUAL "echo")
|
||||||
message(STATUS "Command to create a folder: ")
|
message(STATUS "Command to create a folder: ")
|
||||||
string(REPLACE ";" " " GCOVR_FOLDER_CMD_SPACED "${GCOVR_FOLDER_CMD}")
|
string(REPLACE ";" " " GCOVR_FOLDER_CMD_SPACED "${GCOVR_FOLDER_CMD}")
|
||||||
message(STATUS "${GCOVR_FOLDER_CMD_SPACED}")
|
message(STATUS "${GCOVR_FOLDER_CMD_SPACED}")
|
||||||
@@ -469,19 +454,18 @@ function(setup_target_for_coverage_gcovr)
|
|||||||
)
|
)
|
||||||
endfunction() # setup_target_for_coverage_gcovr
|
endfunction() # setup_target_for_coverage_gcovr
|
||||||
|
|
||||||
function(add_code_coverage_to_target name scope)
|
function(append_coverage_compiler_flags)
|
||||||
separate_arguments(COVERAGE_CXX_COMPILER_FLAGS NATIVE_COMMAND "${COVERAGE_CXX_COMPILER_FLAGS}")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
|
||||||
separate_arguments(COVERAGE_C_COMPILER_FLAGS NATIVE_COMMAND "${COVERAGE_C_COMPILER_FLAGS}")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
|
||||||
separate_arguments(COVERAGE_CXX_LINKER_FLAGS NATIVE_COMMAND "${COVERAGE_CXX_LINKER_FLAGS}")
|
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
|
||||||
separate_arguments(COVERAGE_C_LINKER_FLAGS NATIVE_COMMAND "${COVERAGE_C_LINKER_FLAGS}")
|
message(STATUS "Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}")
|
||||||
|
endfunction() # append_coverage_compiler_flags
|
||||||
|
|
||||||
# Add compiler options to the target
|
# Setup coverage for specific library
|
||||||
target_compile_options(${name} ${scope}
|
function(append_coverage_compiler_flags_to_target name)
|
||||||
$<$<COMPILE_LANGUAGE:CXX>:${COVERAGE_CXX_COMPILER_FLAGS}>
|
separate_arguments(_flag_list NATIVE_COMMAND "${COVERAGE_COMPILER_FLAGS}")
|
||||||
$<$<COMPILE_LANGUAGE:C>:${COVERAGE_C_COMPILER_FLAGS}>)
|
target_compile_options(${name} PRIVATE ${_flag_list})
|
||||||
|
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
|
||||||
target_link_libraries (${name} ${scope}
|
target_link_libraries(${name} PRIVATE gcov)
|
||||||
$<$<LINK_LANGUAGE:CXX>:${COVERAGE_CXX_LINKER_FLAGS} gcov>
|
endif()
|
||||||
$<$<LINK_LANGUAGE:C>:${COVERAGE_C_LINKER_FLAGS} gcov>
|
endfunction()
|
||||||
)
|
|
||||||
endfunction() # add_code_coverage_to_target
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ if (static OR MSVC)
|
|||||||
else ()
|
else ()
|
||||||
set (Boost_USE_STATIC_RUNTIME OFF)
|
set (Boost_USE_STATIC_RUNTIME OFF)
|
||||||
endif ()
|
endif ()
|
||||||
find_dependency (Boost
|
find_dependency (Boost 1.70
|
||||||
COMPONENTS
|
COMPONENTS
|
||||||
chrono
|
chrono
|
||||||
container
|
container
|
||||||
@@ -52,3 +52,5 @@ if (TARGET ZLIB::ZLIB)
|
|||||||
set_target_properties(OpenSSL::Crypto PROPERTIES
|
set_target_properties(OpenSSL::Crypto PROPERTIES
|
||||||
INTERFACE_LINK_LIBRARIES ZLIB::ZLIB)
|
INTERFACE_LINK_LIBRARIES ZLIB::ZLIB)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
include ("${CMAKE_CURRENT_LIST_DIR}/RippleTargets.cmake")
|
||||||
|
|||||||
@@ -16,13 +16,16 @@ set(CMAKE_CXX_EXTENSIONS OFF)
|
|||||||
target_compile_definitions (common
|
target_compile_definitions (common
|
||||||
INTERFACE
|
INTERFACE
|
||||||
$<$<CONFIG:Debug>:DEBUG _DEBUG>
|
$<$<CONFIG:Debug>:DEBUG _DEBUG>
|
||||||
$<$<AND:$<BOOL:${profile}>,$<NOT:$<BOOL:${assert}>>>:NDEBUG>)
|
#[===[
|
||||||
# ^^^^ NOTE: CMAKE release builds already have NDEBUG
|
NOTE: CMAKE release builds already have NDEBUG defined, so no need to add it
|
||||||
# defined, so no need to add it explicitly except for
|
explicitly except for the special case of (profile ON) and (assert OFF).
|
||||||
# this special case of (profile ON) and (assert OFF)
|
Presumably this is because we don't want profile builds asserting unless
|
||||||
# -- presumably this is because we don't want profile
|
asserts were specifically requested.
|
||||||
# builds asserting unless asserts were specifically
|
]===]
|
||||||
# requested
|
$<$<AND:$<BOOL:${profile}>,$<NOT:$<BOOL:${assert}>>>:NDEBUG>
|
||||||
|
# TODO: Remove once we have migrated functions from OpenSSL 1.x to 3.x.
|
||||||
|
OPENSSL_SUPPRESS_DEPRECATED
|
||||||
|
)
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
# remove existing exception flag since we set it to -EHa
|
# remove existing exception flag since we set it to -EHa
|
||||||
|
|||||||
@@ -72,7 +72,10 @@ include(target_link_modules)
|
|||||||
|
|
||||||
# Level 01
|
# Level 01
|
||||||
add_module(xrpl beast)
|
add_module(xrpl beast)
|
||||||
target_link_libraries(xrpl.libxrpl.beast PUBLIC xrpl.imports.main)
|
target_link_libraries(xrpl.libxrpl.beast PUBLIC
|
||||||
|
xrpl.imports.main
|
||||||
|
xrpl.libpb
|
||||||
|
)
|
||||||
|
|
||||||
# Level 02
|
# Level 02
|
||||||
add_module(xrpl basics)
|
add_module(xrpl basics)
|
||||||
@@ -108,12 +111,6 @@ target_link_libraries(xrpl.libxrpl.net PUBLIC
|
|||||||
add_module(xrpl server)
|
add_module(xrpl server)
|
||||||
target_link_libraries(xrpl.libxrpl.server PUBLIC xrpl.libxrpl.protocol)
|
target_link_libraries(xrpl.libxrpl.server PUBLIC xrpl.libxrpl.protocol)
|
||||||
|
|
||||||
add_module(xrpl ledger)
|
|
||||||
target_link_libraries(xrpl.libxrpl.ledger PUBLIC
|
|
||||||
xrpl.libxrpl.basics
|
|
||||||
xrpl.libxrpl.json
|
|
||||||
xrpl.libxrpl.protocol
|
|
||||||
)
|
|
||||||
|
|
||||||
add_library(xrpl.libxrpl)
|
add_library(xrpl.libxrpl)
|
||||||
set_target_properties(xrpl.libxrpl PROPERTIES OUTPUT_NAME xrpl)
|
set_target_properties(xrpl.libxrpl PROPERTIES OUTPUT_NAME xrpl)
|
||||||
@@ -134,7 +131,6 @@ target_link_modules(xrpl PUBLIC
|
|||||||
resource
|
resource
|
||||||
server
|
server
|
||||||
net
|
net
|
||||||
ledger
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# All headers in libxrpl are in modules.
|
# All headers in libxrpl are in modules.
|
||||||
|
|||||||
@@ -11,9 +11,6 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
|||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include(ProcessorCount)
|
|
||||||
ProcessorCount(PROCESSOR_COUNT)
|
|
||||||
|
|
||||||
include(CodeCoverage)
|
include(CodeCoverage)
|
||||||
|
|
||||||
# The instructions for these commands come from the `CodeCoverage` module,
|
# The instructions for these commands come from the `CodeCoverage` module,
|
||||||
@@ -29,13 +26,13 @@ list(APPEND GCOVR_ADDITIONAL_ARGS
|
|||||||
--exclude-throw-branches
|
--exclude-throw-branches
|
||||||
--exclude-noncode-lines
|
--exclude-noncode-lines
|
||||||
--exclude-unreachable-branches -s
|
--exclude-unreachable-branches -s
|
||||||
-j ${PROCESSOR_COUNT})
|
-j ${coverage_test_parallelism})
|
||||||
|
|
||||||
setup_target_for_coverage_gcovr(
|
setup_target_for_coverage_gcovr(
|
||||||
NAME coverage
|
NAME coverage
|
||||||
FORMAT ${coverage_format}
|
FORMAT ${coverage_format}
|
||||||
EXCLUDE "src/test" "src/tests" "include/xrpl/beast/test" "include/xrpl/beast/unit_test" "${CMAKE_BINARY_DIR}/pb-xrpl.libpb"
|
EXECUTABLE rippled
|
||||||
DEPENDENCIES rippled xrpl.tests
|
EXECUTABLE_ARGS --unittest$<$<BOOL:${coverage_test}>:=${coverage_test}> --unittest-jobs ${coverage_test_parallelism} --quiet --unittest-log
|
||||||
|
EXCLUDE "src/test" "include/xrpl/beast/test" "include/xrpl/beast/unit_test" "${CMAKE_BINARY_DIR}/pb-xrpl.libpb"
|
||||||
|
DEPENDENCIES rippled
|
||||||
)
|
)
|
||||||
|
|
||||||
add_code_coverage_to_target(opts INTERFACE)
|
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ install (
|
|||||||
xrpl.libxrpl.json
|
xrpl.libxrpl.json
|
||||||
xrpl.libxrpl.protocol
|
xrpl.libxrpl.protocol
|
||||||
xrpl.libxrpl.resource
|
xrpl.libxrpl.resource
|
||||||
xrpl.libxrpl.ledger
|
|
||||||
xrpl.libxrpl.server
|
xrpl.libxrpl.server
|
||||||
xrpl.libxrpl.net
|
xrpl.libxrpl.net
|
||||||
xrpl.libxrpl
|
xrpl.libxrpl
|
||||||
|
|||||||
@@ -28,11 +28,15 @@ target_compile_options (opts
|
|||||||
$<$<AND:$<BOOL:${is_gcc}>,$<COMPILE_LANGUAGE:CXX>>:-Wsuggest-override>
|
$<$<AND:$<BOOL:${is_gcc}>,$<COMPILE_LANGUAGE:CXX>>:-Wsuggest-override>
|
||||||
$<$<BOOL:${is_gcc}>:-Wno-maybe-uninitialized>
|
$<$<BOOL:${is_gcc}>:-Wno-maybe-uninitialized>
|
||||||
$<$<BOOL:${perf}>:-fno-omit-frame-pointer>
|
$<$<BOOL:${perf}>:-fno-omit-frame-pointer>
|
||||||
|
$<$<AND:$<BOOL:${is_gcc}>,$<BOOL:${coverage}>>:-g --coverage -fprofile-abs-path>
|
||||||
|
$<$<AND:$<BOOL:${is_clang}>,$<BOOL:${coverage}>>:-g --coverage>
|
||||||
$<$<BOOL:${profile}>:-pg>
|
$<$<BOOL:${profile}>:-pg>
|
||||||
$<$<AND:$<BOOL:${is_gcc}>,$<BOOL:${profile}>>:-p>)
|
$<$<AND:$<BOOL:${is_gcc}>,$<BOOL:${profile}>>:-p>)
|
||||||
|
|
||||||
target_link_libraries (opts
|
target_link_libraries (opts
|
||||||
INTERFACE
|
INTERFACE
|
||||||
|
$<$<AND:$<BOOL:${is_gcc}>,$<BOOL:${coverage}>>:-g --coverage -fprofile-abs-path>
|
||||||
|
$<$<AND:$<BOOL:${is_clang}>,$<BOOL:${coverage}>>:-g --coverage>
|
||||||
$<$<BOOL:${profile}>:-pg>
|
$<$<BOOL:${profile}>:-pg>
|
||||||
$<$<AND:$<BOOL:${is_gcc}>,$<BOOL:${profile}>>:-p>)
|
$<$<AND:$<BOOL:${is_gcc}>,$<BOOL:${profile}>>:-p>)
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#[===================================================================[
|
#[===================================================================[
|
||||||
sanity checks
|
convenience variables and sanity checks
|
||||||
#]===================================================================]
|
#]===================================================================]
|
||||||
|
|
||||||
get_property(is_multiconfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
get_property(is_multiconfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||||
@@ -16,19 +16,39 @@ if (NOT is_multiconfig)
|
|||||||
endif ()
|
endif ()
|
||||||
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
|
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES ".*Clang") # both Clang and AppleClang
|
||||||
set (is_clang TRUE)
|
set (is_clang TRUE)
|
||||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND
|
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND
|
||||||
CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16.0)
|
CMAKE_CXX_COMPILER_VERSION VERSION_LESS 8.0)
|
||||||
message (FATAL_ERROR "This project requires clang 16 or later")
|
message (FATAL_ERROR "This project requires clang 8 or later")
|
||||||
endif ()
|
endif ()
|
||||||
|
# TODO min AppleClang version check ?
|
||||||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||||
set (is_gcc TRUE)
|
set (is_gcc TRUE)
|
||||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.0)
|
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 8.0)
|
||||||
message (FATAL_ERROR "This project requires GCC 12 or later")
|
message (FATAL_ERROR "This project requires GCC 8 or later")
|
||||||
endif ()
|
endif ()
|
||||||
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
|
# check for in-source build and fail
|
||||||
if ("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
|
if ("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
|
||||||
message (FATAL_ERROR "Builds (in-source) are not allowed in "
|
message (FATAL_ERROR "Builds (in-source) are not allowed in "
|
||||||
|
|||||||
@@ -1,25 +1,10 @@
|
|||||||
#[===================================================================[
|
#[===================================================================[
|
||||||
declare options and variables
|
declare user options/settings
|
||||||
#]===================================================================]
|
#]===================================================================]
|
||||||
|
|
||||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
include(ProcessorCount)
|
||||||
set (is_linux TRUE)
|
|
||||||
else()
|
|
||||||
set(is_linux FALSE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if("$ENV{CI}" STREQUAL "true" OR "$ENV{CONTINUOUS_INTEGRATION}" STREQUAL "true")
|
ProcessorCount(PROCESSOR_COUNT)
|
||||||
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)
|
option(assert "Enables asserts, even in release builds" OFF)
|
||||||
|
|
||||||
@@ -40,49 +25,35 @@ if(unity)
|
|||||||
endif()
|
endif()
|
||||||
set(CMAKE_UNITY_BUILD ON CACHE BOOL "Do a unity build")
|
set(CMAKE_UNITY_BUILD ON CACHE BOOL "Do a unity build")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(is_clang AND is_linux)
|
if(is_clang AND is_linux)
|
||||||
option(voidstar "Enable Antithesis instrumentation." OFF)
|
option(voidstar "Enable Antithesis instrumentation." OFF)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(is_gcc OR is_clang)
|
if(is_gcc OR is_clang)
|
||||||
include(ProcessorCount)
|
|
||||||
ProcessorCount(PROCESSOR_COUNT)
|
|
||||||
|
|
||||||
option(coverage "Generates coverage info." OFF)
|
option(coverage "Generates coverage info." OFF)
|
||||||
option(profile "Add profiling flags" 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
|
set(coverage_format "html-details" CACHE STRING
|
||||||
"Output format of the coverage report.")
|
"Output format of the coverage report.")
|
||||||
set(coverage_extra_args "" CACHE STRING
|
set(coverage_extra_args "" CACHE STRING
|
||||||
"Additional arguments to pass to gcovr.")
|
"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)
|
option(wextra "compile with extra gcc/clang warnings enabled" ON)
|
||||||
else()
|
else()
|
||||||
set(profile OFF CACHE BOOL "gcc/clang only" FORCE)
|
set(profile OFF CACHE BOOL "gcc/clang only" FORCE)
|
||||||
set(coverage 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)
|
set(wextra OFF CACHE BOOL "gcc/clang only" FORCE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(is_linux)
|
if(is_linux)
|
||||||
option(BUILD_SHARED_LIBS "build shared ripple libraries" OFF)
|
option(BUILD_SHARED_LIBS "build shared ripple libraries" OFF)
|
||||||
option(static "link protobuf, openssl, libc++, and boost statically" ON)
|
option(static "link protobuf, openssl, libc++, and boost statically" ON)
|
||||||
option(perf "Enables flags that assist with perf recording" OFF)
|
option(perf "Enables flags that assist with perf recording" OFF)
|
||||||
option(use_gold "enables detection of gold (binutils) linker" ON)
|
option(use_gold "enables detection of gold (binutils) linker" ON)
|
||||||
option(use_mold "enables detection of mold (binutils) linker" ON)
|
option(use_mold "enables detection of mold (binutils) linker" ON)
|
||||||
# Set a default value for the log flag based on the build type.
|
|
||||||
# This provides a sensible default (on for debug, off for release)
|
|
||||||
# while still allowing the user to override it for any build.
|
|
||||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
|
||||||
set(TRUNCATED_LOGS_DEFAULT ON)
|
|
||||||
else()
|
|
||||||
set(TRUNCATED_LOGS_DEFAULT OFF)
|
|
||||||
endif()
|
|
||||||
option(TRUNCATED_THREAD_NAME_LOGS
|
|
||||||
"Show warnings about truncated thread names on Linux."
|
|
||||||
${TRUNCATED_LOGS_DEFAULT}
|
|
||||||
)
|
|
||||||
if(TRUNCATED_THREAD_NAME_LOGS)
|
|
||||||
add_compile_definitions(TRUNCATED_THREAD_NAME_LOGS)
|
|
||||||
endif()
|
|
||||||
else()
|
else()
|
||||||
# we are not ready to allow shared-libs on windows because it would require
|
# we are not ready to allow shared-libs on windows because it would require
|
||||||
# export declarations. On macos it's more feasible, but static openssl
|
# export declarations. On macos it's more feasible, but static openssl
|
||||||
@@ -93,13 +64,11 @@ else()
|
|||||||
set(use_gold OFF CACHE BOOL "gold linker, linux only" FORCE)
|
set(use_gold OFF CACHE BOOL "gold linker, linux only" FORCE)
|
||||||
set(use_mold OFF CACHE BOOL "mold linker, linux only" FORCE)
|
set(use_mold OFF CACHE BOOL "mold linker, linux only" FORCE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(is_clang)
|
if(is_clang)
|
||||||
option(use_lld "enables detection of lld linker" ON)
|
option(use_lld "enables detection of lld linker" ON)
|
||||||
else()
|
else()
|
||||||
set(use_lld OFF CACHE BOOL "try lld linker, clang only" FORCE)
|
set(use_lld OFF CACHE BOOL "try lld linker, clang only" FORCE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
option(jemalloc "Enables jemalloc for heap profiling" OFF)
|
option(jemalloc "Enables jemalloc for heap profiling" OFF)
|
||||||
option(werr "treat warnings as errors" OFF)
|
option(werr "treat warnings as errors" OFF)
|
||||||
option(local_protobuf
|
option(local_protobuf
|
||||||
@@ -133,26 +102,38 @@ if(san)
|
|||||||
message(FATAL_ERROR "${san} sanitizer does not seem to be supported by your compiler")
|
message(FATAL_ERROR "${san} sanitizer does not seem to be supported by your compiler")
|
||||||
endif()
|
endif()
|
||||||
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
|
# the remaining options are obscure and rarely used
|
||||||
option(beast_no_unit_test_inline
|
option(beast_no_unit_test_inline
|
||||||
"Prevents unit test definitions from being inserted into global table"
|
"Prevents unit test definitions from being inserted into global table"
|
||||||
OFF)
|
OFF)
|
||||||
option(single_io_service_thread
|
option(single_io_service_thread
|
||||||
"Restricts the number of threads calling io_service::run to one. \
|
"Restricts the number of threads calling io_context::run to one. \
|
||||||
This can be useful when debugging."
|
This can be useful when debugging."
|
||||||
OFF)
|
OFF)
|
||||||
option(boost_show_deprecated
|
option(boost_show_deprecated
|
||||||
"Allow boost to fail on deprecated usage. Only useful if you're trying\
|
"Allow boost to fail on deprecated usage. Only useful if you're trying\
|
||||||
to find deprecated calls."
|
to find deprecated calls."
|
||||||
OFF)
|
OFF)
|
||||||
|
option(beast_hashers
|
||||||
|
"Use local implementations for sha/ripemd hashes (experimental, not recommended)"
|
||||||
|
OFF)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
option(beast_disable_autolink "Disables autolinking of system libraries on WIN32" OFF)
|
option(beast_disable_autolink "Disables autolinking of system libraries on WIN32" OFF)
|
||||||
else()
|
else()
|
||||||
set(beast_disable_autolink OFF CACHE BOOL "WIN32 only" FORCE)
|
set(beast_disable_autolink OFF CACHE BOOL "WIN32 only" FORCE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(coverage)
|
if(coverage)
|
||||||
message(STATUS "coverage build requested - forcing Debug build")
|
message(STATUS "coverage build requested - forcing Debug build")
|
||||||
set(CMAKE_BUILD_TYPE Debug CACHE STRING "build type" FORCE)
|
set(CMAKE_BUILD_TYPE Debug CACHE STRING "build type" FORCE)
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ target_link_libraries(ripple_boost
|
|||||||
Boost::date_time
|
Boost::date_time
|
||||||
Boost::filesystem
|
Boost::filesystem
|
||||||
Boost::json
|
Boost::json
|
||||||
|
Boost::process
|
||||||
Boost::program_options
|
Boost::program_options
|
||||||
Boost::regex
|
Boost::regex
|
||||||
Boost::system
|
Boost::system
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ function(xrpl_add_test name)
|
|||||||
"${CMAKE_CURRENT_SOURCE_DIR}/${name}/*.cpp"
|
"${CMAKE_CURRENT_SOURCE_DIR}/${name}/*.cpp"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/${name}.cpp"
|
"${CMAKE_CURRENT_SOURCE_DIR}/${name}.cpp"
|
||||||
)
|
)
|
||||||
add_executable(${target} ${ARGN} ${sources})
|
add_executable(${target} EXCLUDE_FROM_ALL ${ARGN} ${sources})
|
||||||
|
|
||||||
isolate_headers(
|
isolate_headers(
|
||||||
${target}
|
${target}
|
||||||
@@ -22,4 +22,20 @@ function(xrpl_add_test name)
|
|||||||
UNITY_BUILD_BATCH_SIZE 0) # Adjust as needed
|
UNITY_BUILD_BATCH_SIZE 0) # Adjust as needed
|
||||||
|
|
||||||
add_test(NAME ${target} COMMAND ${target})
|
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()
|
endfunction()
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
"rocksdb/10.0.1#85537f46e538974d67da0c3977de48ac%1756234304.347",
|
"rocksdb/10.0.1#85537f46e538974d67da0c3977de48ac%1756234304.347",
|
||||||
"re2/20230301#dfd6e2bf050eb90ddd8729cfb4c844a4%1756234257.976",
|
"re2/20230301#dfd6e2bf050eb90ddd8729cfb4c844a4%1756234257.976",
|
||||||
"protobuf/3.21.12#d927114e28de9f4691a6bbcdd9a529d1%1756234251.614",
|
"protobuf/3.21.12#d927114e28de9f4691a6bbcdd9a529d1%1756234251.614",
|
||||||
"openssl/1.1.1w#a8f0792d7c5121b954578a7149d23e03%1756223730.729",
|
"openssl/3.5.2#0c5a5e15ae569f45dff57adcf1770cf7%1756234259.61",
|
||||||
"nudb/2.0.9#c62cfd501e57055a7e0d8ee3d5e5427d%1756234237.107",
|
"nudb/2.0.9#c62cfd501e57055a7e0d8ee3d5e5427d%1756234237.107",
|
||||||
"lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1756234228.999",
|
"lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1756234228.999",
|
||||||
"libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1756223727.64",
|
"libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1756223727.64",
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
"date/3.0.4#f74bbba5a08fa388256688743136cb6f%1756234217.493",
|
"date/3.0.4#f74bbba5a08fa388256688743136cb6f%1756234217.493",
|
||||||
"c-ares/1.34.5#b78b91e7cfb1f11ce777a285bbf169c6%1756234217.915",
|
"c-ares/1.34.5#b78b91e7cfb1f11ce777a285bbf169c6%1756234217.915",
|
||||||
"bzip2/1.0.8#00b4a4658791c1f06914e087f0e792f5%1756234261.716",
|
"bzip2/1.0.8#00b4a4658791c1f06914e087f0e792f5%1756234261.716",
|
||||||
"boost/1.83.0#5d975011d65b51abb2d2f6eb8386b368%1754325043.336",
|
"boost/1.88.0#8852c0b72ce8271fb8ff7c53456d4983%1756223752.326",
|
||||||
"abseil/20230802.1#f0f91485b111dc9837a68972cb19ca7b%1756234220.907"
|
"abseil/20230802.1#f0f91485b111dc9837a68972cb19ca7b%1756234220.907"
|
||||||
],
|
],
|
||||||
"build_requires": [
|
"build_requires": [
|
||||||
@@ -46,11 +46,11 @@
|
|||||||
"lz4/1.10.0"
|
"lz4/1.10.0"
|
||||||
],
|
],
|
||||||
"boost/1.83.0": [
|
"boost/1.83.0": [
|
||||||
"boost/1.83.0"
|
"boost/1.88.0"
|
||||||
],
|
],
|
||||||
"sqlite3/3.44.2": [
|
"sqlite3/3.44.2": [
|
||||||
"sqlite3/3.49.1"
|
"sqlite3/3.49.1"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"config_requires": []
|
"config_requires": []
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
# Global configuration for Conan. This is used to set the number of parallel
|
# Global configuration for Conan. This is used to set the number of parallel
|
||||||
# downloads and uploads.
|
# downloads, uploads, and build jobs. The verbosity is set to verbose to
|
||||||
|
# provide more information during the build process.
|
||||||
core:non_interactive=True
|
core:non_interactive=True
|
||||||
core.download:parallel={{ os.cpu_count() }}
|
core.download:parallel={{ os.cpu_count() }}
|
||||||
core.upload: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]
|
[conf]
|
||||||
{% if compiler == "clang" and compiler_version >= 19 %}
|
{% if compiler == "clang" and compiler_version >= 19 %}
|
||||||
grpc/1.50.1:tools.build:cxxflags+=['-Wno-missing-template-arg-list-after-template-kw']
|
tools.build:cxxflags=['-Wno-missing-template-arg-list-after-template-kw']
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if compiler == "apple-clang" and compiler_version >= 17 %}
|
{% if compiler == "apple-clang" and compiler_version >= 17 %}
|
||||||
grpc/1.50.1:tools.build:cxxflags+=['-Wno-missing-template-arg-list-after-template-kw']
|
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 %}
|
{% endif %}
|
||||||
{% if compiler == "gcc" and compiler_version < 13 %}
|
{% if compiler == "gcc" and compiler_version < 13 %}
|
||||||
tools.build:cxxflags+=['-Wno-restrict']
|
tools.build:cxxflags=['-Wno-restrict']
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
[tool_requires]
|
||||||
|
!cmake/*: cmake/[>=3 <4]
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class Xrpl(ConanFile):
|
|||||||
'grpc/1.50.1',
|
'grpc/1.50.1',
|
||||||
'libarchive/3.8.1',
|
'libarchive/3.8.1',
|
||||||
'nudb/2.0.9',
|
'nudb/2.0.9',
|
||||||
'openssl/1.1.1w',
|
'openssl/3.5.2',
|
||||||
'soci/4.0.3',
|
'soci/4.0.3',
|
||||||
'zlib/1.3.1',
|
'zlib/1.3.1',
|
||||||
]
|
]
|
||||||
@@ -100,11 +100,13 @@ class Xrpl(ConanFile):
|
|||||||
def configure(self):
|
def configure(self):
|
||||||
if self.settings.compiler == 'apple-clang':
|
if self.settings.compiler == 'apple-clang':
|
||||||
self.options['boost'].visibility = 'global'
|
self.options['boost'].visibility = 'global'
|
||||||
|
if self.settings.compiler in ['clang', 'gcc']:
|
||||||
|
self.options['boost'].without_cobalt = True
|
||||||
|
|
||||||
def requirements(self):
|
def requirements(self):
|
||||||
# Conan 2 requires transitive headers to be specified
|
# Conan 2 requires transitive headers to be specified
|
||||||
transitive_headers_opt = {'transitive_headers': True} if conan_version.split('.')[0] == '2' else {}
|
transitive_headers_opt = {'transitive_headers': True} if conan_version.split('.')[0] == '2' else {}
|
||||||
self.requires('boost/1.83.0', force=True, **transitive_headers_opt)
|
self.requires('boost/1.88.0', force=True, **transitive_headers_opt)
|
||||||
self.requires('date/3.0.4', **transitive_headers_opt)
|
self.requires('date/3.0.4', **transitive_headers_opt)
|
||||||
self.requires('lz4/1.10.0', force=True)
|
self.requires('lz4/1.10.0', force=True)
|
||||||
self.requires('protobuf/3.21.12', force=True)
|
self.requires('protobuf/3.21.12', force=True)
|
||||||
@@ -175,6 +177,7 @@ class Xrpl(ConanFile):
|
|||||||
'boost::filesystem',
|
'boost::filesystem',
|
||||||
'boost::json',
|
'boost::json',
|
||||||
'boost::program_options',
|
'boost::program_options',
|
||||||
|
'boost::process',
|
||||||
'boost::regex',
|
'boost::regex',
|
||||||
'boost::system',
|
'boost::system',
|
||||||
'boost::thread',
|
'boost::thread',
|
||||||
|
|||||||
2
external/secp256k1/include/secp256k1.h
vendored
2
external/secp256k1/include/secp256k1.h
vendored
@@ -541,7 +541,7 @@ SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact(
|
|||||||
/** Verify an ECDSA signature.
|
/** Verify an ECDSA signature.
|
||||||
*
|
*
|
||||||
* Returns: 1: correct signature
|
* Returns: 1: correct signature
|
||||||
* 0: incorrect or unparsable signature
|
* 0: incorrect or unparseable signature
|
||||||
* Args: ctx: pointer to a context object
|
* Args: ctx: pointer to a context object
|
||||||
* In: sig: the signature being verified.
|
* In: sig: the signature being verified.
|
||||||
* msghash32: the 32-byte message hash being verified.
|
* msghash32: the 32-byte message hash being verified.
|
||||||
|
|||||||
@@ -166,29 +166,17 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
constexpr E const&
|
constexpr E const&
|
||||||
error() const&
|
error() const
|
||||||
{
|
{
|
||||||
return Base::error();
|
return Base::error();
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr E&
|
constexpr E&
|
||||||
error() &
|
error()
|
||||||
{
|
{
|
||||||
return Base::error();
|
return Base::error();
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr E&&
|
|
||||||
error() &&
|
|
||||||
{
|
|
||||||
return std::move(Base::error());
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr E const&&
|
|
||||||
error() const&&
|
|
||||||
{
|
|
||||||
return std::move(Base::error());
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr explicit
|
constexpr explicit
|
||||||
operator bool() const
|
operator bool() const
|
||||||
{
|
{
|
||||||
@@ -245,29 +233,17 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
constexpr E const&
|
constexpr E const&
|
||||||
error() const&
|
error() const
|
||||||
{
|
{
|
||||||
return Base::error();
|
return Base::error();
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr E&
|
constexpr E&
|
||||||
error() &
|
error()
|
||||||
{
|
{
|
||||||
return Base::error();
|
return Base::error();
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr E&&
|
|
||||||
error() &&
|
|
||||||
{
|
|
||||||
return std::move(Base::error());
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr E const&&
|
|
||||||
error() const&&
|
|
||||||
{
|
|
||||||
return std::move(Base::error());
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr explicit
|
constexpr explicit
|
||||||
operator bool() const
|
operator bool() const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -654,14 +654,12 @@ SharedWeakUnion<T>::convertToWeak()
|
|||||||
break;
|
break;
|
||||||
case destroy:
|
case destroy:
|
||||||
// We just added a weak ref. How could we destroy?
|
// We just added a weak ref. How could we destroy?
|
||||||
// LCOV_EXCL_START
|
|
||||||
UNREACHABLE(
|
UNREACHABLE(
|
||||||
"ripple::SharedWeakUnion::convertToWeak : destroying freshly "
|
"ripple::SharedWeakUnion::convertToWeak : destroying freshly "
|
||||||
"added ref");
|
"added ref");
|
||||||
delete p;
|
delete p;
|
||||||
unsafeSetRawPtr(nullptr);
|
unsafeSetRawPtr(nullptr);
|
||||||
return true; // Should never happen
|
return true; // Should never happen
|
||||||
// LCOV_EXCL_STOP
|
|
||||||
case partialDestroy:
|
case partialDestroy:
|
||||||
// This is a weird case. We just converted the last strong
|
// This is a weird case. We just converted the last strong
|
||||||
// pointer to a weak pointer.
|
// pointer to a weak pointer.
|
||||||
|
|||||||
@@ -20,12 +20,8 @@
|
|||||||
#ifndef RIPPLE_BASICS_NUMBER_H_INCLUDED
|
#ifndef RIPPLE_BASICS_NUMBER_H_INCLUDED
|
||||||
#define RIPPLE_BASICS_NUMBER_H_INCLUDED
|
#define RIPPLE_BASICS_NUMBER_H_INCLUDED
|
||||||
|
|
||||||
#include <xrpl/beast/utility/instrumentation.h>
|
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <functional>
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <optional>
|
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -36,252 +32,31 @@ class Number;
|
|||||||
std::string
|
std::string
|
||||||
to_string(Number const& amount);
|
to_string(Number const& amount);
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
constexpr std::optional<int>
|
|
||||||
logTen(T value)
|
|
||||||
{
|
|
||||||
int log = 0;
|
|
||||||
while (value >= 10 && value % 10 == 0)
|
|
||||||
{
|
|
||||||
value /= 10;
|
|
||||||
++log;
|
|
||||||
}
|
|
||||||
if (value == 1)
|
|
||||||
return log;
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
constexpr bool
|
|
||||||
isPowerOfTen(T value)
|
|
||||||
{
|
|
||||||
return logTen(value).has_value();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** MantissaRange defines a range for the mantissa of a normalized Number.
|
|
||||||
*
|
|
||||||
* The mantissa is in the range [min, max], where
|
|
||||||
* * min is a power of 10, and
|
|
||||||
* * max = min * 10 - 1.
|
|
||||||
*
|
|
||||||
* The mantissa_scale enum indicates whether the range is "small" or "large".
|
|
||||||
* This intentionally restricts the number of MantissaRanges that can be
|
|
||||||
* instantiated to two: one for each scale.
|
|
||||||
*
|
|
||||||
* The "small" scale is based on the behavior of STAmount for IOUs. It has a min
|
|
||||||
* value of 10^15, and a max value of 10^16-1. This was sufficient for
|
|
||||||
* uses before Lending Protocol was implemented, mostly related to AMM.
|
|
||||||
*
|
|
||||||
* However, it does not have sufficient precision to represent the full integer
|
|
||||||
* range of int64_t values (-2^63 to 2^63-1), which are needed for XRP and MPT
|
|
||||||
* values. The implementation of SingleAssetVault, and LendingProtocol need to
|
|
||||||
* represent those integer values accurately and precisely, both for the
|
|
||||||
* STNumber field type, and for internal calculations. That necessitated the
|
|
||||||
* "large" scale.
|
|
||||||
*
|
|
||||||
* The "large" scale is intended to represent all values that can be represented
|
|
||||||
* by an STAmount - IOUs, XRP, and MPTs. It has a min value of 10^18, and a max
|
|
||||||
* value of 10^19-1.
|
|
||||||
*
|
|
||||||
* Note that if the mentioned amendments are eventually retired, this class
|
|
||||||
* should be left in place, but the "small" scale option should be removed. This
|
|
||||||
* will allow for future expansion beyond 64-bits if it is ever needed.
|
|
||||||
*/
|
|
||||||
struct MantissaRange
|
|
||||||
{
|
|
||||||
using rep = std::uint64_t;
|
|
||||||
enum mantissa_scale { small, large };
|
|
||||||
|
|
||||||
explicit constexpr MantissaRange(mantissa_scale scale_)
|
|
||||||
: min(getMin(scale_))
|
|
||||||
, max(min * 10 - 1)
|
|
||||||
, log(logTen(min).value_or(-1))
|
|
||||||
, scale(scale_)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
rep min;
|
|
||||||
rep max;
|
|
||||||
int log;
|
|
||||||
mantissa_scale scale;
|
|
||||||
|
|
||||||
private:
|
|
||||||
static constexpr rep
|
|
||||||
getMin(mantissa_scale scale_)
|
|
||||||
{
|
|
||||||
switch (scale_)
|
|
||||||
{
|
|
||||||
case small:
|
|
||||||
return 1'000'000'000'000'000ULL;
|
|
||||||
case large:
|
|
||||||
return 1'000'000'000'000'000'000ULL;
|
|
||||||
default:
|
|
||||||
// Since this can never be called outside a non-constexpr
|
|
||||||
// context, this throw assures that the build fails if an
|
|
||||||
// invalid scale is used.
|
|
||||||
throw std::runtime_error("Unknown mantissa scale");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Like std::integral, but only 64-bit integral types.
|
|
||||||
template <class T>
|
|
||||||
concept Integral64 =
|
|
||||||
std::is_same_v<T, std::int64_t> || std::is_same_v<T, std::uint64_t>;
|
|
||||||
|
|
||||||
/** Number is a floating point type that can represent a wide range of values.
|
|
||||||
*
|
|
||||||
* It can represent all values that can be represented by an STAmount -
|
|
||||||
* regardless of asset type - XRPAmount, MPTAmount, and IOUAmount, with at least
|
|
||||||
* as much precision as those types require.
|
|
||||||
*
|
|
||||||
* ---- Internal Representation ----
|
|
||||||
*
|
|
||||||
* Internally, Number is represented with three values:
|
|
||||||
* 1. a bool sign flag,
|
|
||||||
* 2. a std::uint64_t mantissa,
|
|
||||||
* 3. an int exponent.
|
|
||||||
*
|
|
||||||
* The internal mantissa is an unsigned integer in the range defined by the
|
|
||||||
* current MantissaRange. The exponent is an integer in the range
|
|
||||||
* [minExponent, maxExponent].
|
|
||||||
*
|
|
||||||
* See the description of MantissaRange for more details on the ranges.
|
|
||||||
*
|
|
||||||
* A non-zero mantissa is (almost) always normalized, meaning it and the
|
|
||||||
* exponent are grown or shrunk until the mantissa is in the range
|
|
||||||
* [MantissaRange.min, MantissaRange.max].
|
|
||||||
*
|
|
||||||
* Note:
|
|
||||||
* 1. Normalization can be disabled by using the "unchecked" ctor tag. This
|
|
||||||
* should only be used at specific conversion points, some constexpr
|
|
||||||
* values, and in unit tests.
|
|
||||||
* 2. The max of the "large" range, 10^19-1, is the largest 10^X-1 value that
|
|
||||||
* fits in an unsigned 64-bit number. (10^19-1 < 2^64-1 and
|
|
||||||
* 10^20-1 > 2^64-1). This avoids under- and overflows.
|
|
||||||
*
|
|
||||||
* ---- External Interface ----
|
|
||||||
*
|
|
||||||
* The external interface of Number consists of a std::int64_t mantissa, which
|
|
||||||
* is restricted to 63-bits, and an int exponent, which must be in the range
|
|
||||||
* [minExponent, maxExponent]. The range of the mantissa depends on which
|
|
||||||
* MantissaRange is currently active. For the "short" range, the mantissa will
|
|
||||||
* be between 10^15 and 10^16-1. For the "large" range, the mantissa will be
|
|
||||||
* between -(2^63-1) and 2^63-1. As noted above, the "large" range is needed to
|
|
||||||
* represent the full range of valid XRP and MPT integer values accurately.
|
|
||||||
*
|
|
||||||
* Note:
|
|
||||||
* 1. 2^63-1 is between 10^18 and 10^19-1, which are the limits of the "large"
|
|
||||||
* mantissa range.
|
|
||||||
* 2. The functions mantissa() and exponent() return the external view of the
|
|
||||||
* Number value, specifically using a signed 63-bit mantissa. This may
|
|
||||||
* require altering the internal representation to fit into that range
|
|
||||||
* before the value is returned. The interface guarantees consistency of
|
|
||||||
* the two values.
|
|
||||||
* 3. Number cannot represent -2^63 (std::numeric_limits<std::int64_t>::min())
|
|
||||||
* as an exact integer, but it doesn't need to, because all asset values
|
|
||||||
* on-ledger are non-negative. This is due to implementation details of
|
|
||||||
* several operations which use unsigned arithmetic internally. This is
|
|
||||||
* sufficient to represent all valid XRP values (where the absolute value
|
|
||||||
* can not exceed INITIAL_XRP: 10^17), and MPT values (where the absolute
|
|
||||||
* value can not exceed maxMPTokenAmount: 2^63-1).
|
|
||||||
*
|
|
||||||
* ---- Mantissa Range Switching ----
|
|
||||||
*
|
|
||||||
* The mantissa range may be changed at runtime via setMantissaScale(). The
|
|
||||||
* default mantissa range is "large". The range is updated whenever transaction
|
|
||||||
* processing begins, based on whether SingleAssetVault or LendingProtocol are
|
|
||||||
* enabled. If either is enabled, the mantissa range is set to "large". If not,
|
|
||||||
* it is set to "small", preserving backward compatibility and correct
|
|
||||||
* "amendment-gating".
|
|
||||||
*
|
|
||||||
* It is extremely unlikely that any more calls to setMantissaScale() will be
|
|
||||||
* needed outside of unit tests.
|
|
||||||
*
|
|
||||||
* ---- Usage With Different Ranges ----
|
|
||||||
*
|
|
||||||
* Outside of unit tests, and existing checks, code that uses Number should not
|
|
||||||
* know or care which mantissa range is active.
|
|
||||||
*
|
|
||||||
* The results of computations using Numbers with a small mantissa may differ
|
|
||||||
* from computations using Numbers with a large mantissa, specifically as it
|
|
||||||
* effects the results after rounding. That is why the large mantissa range is
|
|
||||||
* amendment gated in transaction processing.
|
|
||||||
*
|
|
||||||
* It is extremely unlikely that any more calls to getMantissaScale() will be
|
|
||||||
* needed outside of unit tests.
|
|
||||||
*
|
|
||||||
* Code that uses Number should not assume or check anything about the
|
|
||||||
* mantissa() or exponent() except that they fit into the "large" range
|
|
||||||
* specified in the "External Interface" section.
|
|
||||||
*
|
|
||||||
* ----- Unit Tests -----
|
|
||||||
*
|
|
||||||
* Within unit tests, it may be useful to explicitly switch between the two
|
|
||||||
* ranges, or to check which range is active when checking the results of
|
|
||||||
* computations. If the test is doing the math directly, the
|
|
||||||
* set/getMantissaScale() functions may be most appropriate. However, if the
|
|
||||||
* test has anything to do with transaction processing, it should enable or
|
|
||||||
* disable the amendments that control the mantissa range choice
|
|
||||||
* (SingleAssetVault and LendingProtocol), and/or check if either of those
|
|
||||||
* amendments are enabled to determine which result to expect.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class Number
|
class Number
|
||||||
{
|
{
|
||||||
using rep = std::int64_t;
|
using rep = std::int64_t;
|
||||||
using internalrep = MantissaRange::rep;
|
rep mantissa_{0};
|
||||||
|
|
||||||
bool negative_{false};
|
|
||||||
internalrep mantissa_{0};
|
|
||||||
int exponent_{std::numeric_limits<int>::lowest()};
|
int exponent_{std::numeric_limits<int>::lowest()};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
// The range for the mantissa when normalized
|
||||||
|
constexpr static std::int64_t minMantissa = 1'000'000'000'000'000LL;
|
||||||
|
constexpr static std::int64_t maxMantissa = 9'999'999'999'999'999LL;
|
||||||
|
|
||||||
// The range for the exponent when normalized
|
// The range for the exponent when normalized
|
||||||
constexpr static int minExponent = -32768;
|
constexpr static int minExponent = -32768;
|
||||||
constexpr static int maxExponent = 32768;
|
constexpr static int maxExponent = 32768;
|
||||||
|
|
||||||
constexpr static internalrep maxRep = std::numeric_limits<rep>::max();
|
|
||||||
static_assert(maxRep == 9'223'372'036'854'775'807);
|
|
||||||
static_assert(-maxRep == std::numeric_limits<rep>::min() + 1);
|
|
||||||
|
|
||||||
// May need to make unchecked private
|
|
||||||
struct unchecked
|
struct unchecked
|
||||||
{
|
{
|
||||||
explicit unchecked() = default;
|
explicit unchecked() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Like unchecked, normalized is used with the ctors that take an
|
|
||||||
// internalrep mantissa. Unlike unchecked, those ctors will normalize the
|
|
||||||
// value.
|
|
||||||
// Only unit tests are expected to use this class
|
|
||||||
struct normalized
|
|
||||||
{
|
|
||||||
explicit normalized() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit constexpr Number() = default;
|
explicit constexpr Number() = default;
|
||||||
|
|
||||||
Number(rep mantissa);
|
Number(rep mantissa);
|
||||||
explicit Number(rep mantissa, int exponent);
|
explicit Number(rep mantissa, int exponent);
|
||||||
explicit constexpr Number(
|
explicit constexpr Number(rep mantissa, int exponent, unchecked) noexcept;
|
||||||
bool negative,
|
|
||||||
internalrep mantissa,
|
|
||||||
int exponent,
|
|
||||||
unchecked) noexcept;
|
|
||||||
// Assume unsigned values are... unsigned. i.e. positive
|
|
||||||
explicit constexpr Number(
|
|
||||||
internalrep mantissa,
|
|
||||||
int exponent,
|
|
||||||
unchecked) noexcept;
|
|
||||||
// Only unit tests are expected to use this ctor
|
|
||||||
explicit Number(
|
|
||||||
bool negative,
|
|
||||||
internalrep mantissa,
|
|
||||||
int exponent,
|
|
||||||
normalized);
|
|
||||||
// Assume unsigned values are... unsigned. i.e. positive
|
|
||||||
explicit Number(internalrep mantissa, int exponent, normalized);
|
|
||||||
|
|
||||||
constexpr rep
|
constexpr rep
|
||||||
mantissa() const noexcept;
|
mantissa() const noexcept;
|
||||||
@@ -311,11 +86,11 @@ public:
|
|||||||
Number&
|
Number&
|
||||||
operator/=(Number const& x);
|
operator/=(Number const& x);
|
||||||
|
|
||||||
static Number
|
static constexpr Number
|
||||||
min() noexcept;
|
min() noexcept;
|
||||||
static Number
|
static constexpr Number
|
||||||
max() noexcept;
|
max() noexcept;
|
||||||
static Number
|
static constexpr Number
|
||||||
lowest() noexcept;
|
lowest() noexcept;
|
||||||
|
|
||||||
/** Conversions to Number are implicit and conversions away from Number
|
/** Conversions to Number are implicit and conversions away from Number
|
||||||
@@ -329,8 +104,7 @@ public:
|
|||||||
friend constexpr bool
|
friend constexpr bool
|
||||||
operator==(Number const& x, Number const& y) noexcept
|
operator==(Number const& x, Number const& y) noexcept
|
||||||
{
|
{
|
||||||
return x.negative_ == y.negative_ && x.mantissa_ == y.mantissa_ &&
|
return x.mantissa_ == y.mantissa_ && x.exponent_ == y.exponent_;
|
||||||
x.exponent_ == y.exponent_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
friend constexpr bool
|
friend constexpr bool
|
||||||
@@ -344,8 +118,8 @@ public:
|
|||||||
{
|
{
|
||||||
// If the two amounts have different signs (zero is treated as positive)
|
// If the two amounts have different signs (zero is treated as positive)
|
||||||
// then the comparison is true iff the left is negative.
|
// then the comparison is true iff the left is negative.
|
||||||
bool const lneg = x.negative_;
|
bool const lneg = x.mantissa_ < 0;
|
||||||
bool const rneg = y.negative_;
|
bool const rneg = y.mantissa_ < 0;
|
||||||
|
|
||||||
if (lneg != rneg)
|
if (lneg != rneg)
|
||||||
return lneg;
|
return lneg;
|
||||||
@@ -373,11 +147,26 @@ public:
|
|||||||
constexpr int
|
constexpr int
|
||||||
signum() const noexcept
|
signum() const noexcept
|
||||||
{
|
{
|
||||||
return negative_ ? -1 : (mantissa_ ? 1 : 0);
|
return (mantissa_ < 0) ? -1 : (mantissa_ ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Number
|
Number
|
||||||
truncate() const noexcept;
|
truncate() const noexcept
|
||||||
|
{
|
||||||
|
if (exponent_ >= 0 || mantissa_ == 0)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
Number ret = *this;
|
||||||
|
while (ret.exponent_ < 0 && ret.mantissa_ != 0)
|
||||||
|
{
|
||||||
|
ret.exponent_ += 1;
|
||||||
|
ret.mantissa_ /= rep(10);
|
||||||
|
}
|
||||||
|
// We are guaranteed that normalize() will never throw an exception
|
||||||
|
// because exponent is either negative or zero at this point.
|
||||||
|
ret.normalize();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
friend constexpr bool
|
friend constexpr bool
|
||||||
operator>(Number const& x, Number const& y) noexcept
|
operator>(Number const& x, Number const& y) noexcept
|
||||||
@@ -403,15 +192,6 @@ public:
|
|||||||
return os << to_string(x);
|
return os << to_string(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
friend std::string
|
|
||||||
to_string(Number const& amount);
|
|
||||||
|
|
||||||
friend Number
|
|
||||||
root(Number f, unsigned d);
|
|
||||||
|
|
||||||
friend Number
|
|
||||||
root2(Number f);
|
|
||||||
|
|
||||||
// Thread local rounding control. Default is to_nearest
|
// Thread local rounding control. Default is to_nearest
|
||||||
enum rounding_mode { to_nearest, towards_zero, downward, upward };
|
enum rounding_mode { to_nearest, towards_zero, downward, upward };
|
||||||
static rounding_mode
|
static rounding_mode
|
||||||
@@ -420,206 +200,42 @@ public:
|
|||||||
static rounding_mode
|
static rounding_mode
|
||||||
setround(rounding_mode mode);
|
setround(rounding_mode mode);
|
||||||
|
|
||||||
/** Returns which mantissa scale is currently in use for normalization.
|
|
||||||
*
|
|
||||||
* If you think you need to call this outside of unit tests, no you don't.
|
|
||||||
*/
|
|
||||||
static MantissaRange::mantissa_scale
|
|
||||||
getMantissaScale();
|
|
||||||
/** Changes which mantissa scale is used for normalization.
|
|
||||||
*
|
|
||||||
* If you think you need to call this outside of unit tests, no you don't.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
setMantissaScale(MantissaRange::mantissa_scale scale);
|
|
||||||
|
|
||||||
inline static internalrep
|
|
||||||
minMantissa()
|
|
||||||
{
|
|
||||||
return range_.get().min;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static internalrep
|
|
||||||
maxMantissa()
|
|
||||||
{
|
|
||||||
return range_.get().max;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static int
|
|
||||||
mantissaLog()
|
|
||||||
{
|
|
||||||
return range_.get().log;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// oneSmall is needed because the ranges are private
|
|
||||||
constexpr static Number
|
|
||||||
oneSmall();
|
|
||||||
/// oneLarge is needed because the ranges are private
|
|
||||||
constexpr static Number
|
|
||||||
oneLarge();
|
|
||||||
|
|
||||||
// And one is needed because it needs to choose between oneSmall and
|
|
||||||
// oneLarge based on the current range
|
|
||||||
static Number
|
|
||||||
one();
|
|
||||||
|
|
||||||
template <Integral64 T>
|
|
||||||
[[nodiscard]]
|
|
||||||
std::pair<T, int>
|
|
||||||
normalizeToRange(T minMantissa, T maxMantissa) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static thread_local rounding_mode mode_;
|
static thread_local rounding_mode mode_;
|
||||||
// The available ranges for mantissa
|
|
||||||
|
|
||||||
constexpr static MantissaRange smallRange{MantissaRange::small};
|
|
||||||
static_assert(isPowerOfTen(smallRange.min));
|
|
||||||
static_assert(smallRange.min == 1'000'000'000'000'000LL);
|
|
||||||
static_assert(smallRange.max == 9'999'999'999'999'999LL);
|
|
||||||
static_assert(smallRange.log == 15);
|
|
||||||
static_assert(smallRange.min < maxRep);
|
|
||||||
static_assert(smallRange.max < maxRep);
|
|
||||||
constexpr static MantissaRange largeRange{MantissaRange::large};
|
|
||||||
static_assert(isPowerOfTen(largeRange.min));
|
|
||||||
static_assert(largeRange.min == 1'000'000'000'000'000'000ULL);
|
|
||||||
static_assert(largeRange.max == internalrep(9'999'999'999'999'999'999ULL));
|
|
||||||
static_assert(largeRange.log == 18);
|
|
||||||
static_assert(largeRange.min < maxRep);
|
|
||||||
static_assert(largeRange.max > maxRep);
|
|
||||||
|
|
||||||
// The range for the mantissa when normalized.
|
|
||||||
// Use reference_wrapper to avoid making copies, and prevent accidentally
|
|
||||||
// changing the values inside the range.
|
|
||||||
static thread_local std::reference_wrapper<MantissaRange const> range_;
|
|
||||||
|
|
||||||
void
|
void
|
||||||
normalize();
|
normalize();
|
||||||
|
constexpr bool
|
||||||
/** Normalize Number components to an arbitrary range.
|
|
||||||
*
|
|
||||||
* min/maxMantissa are parameters because this function is used by both
|
|
||||||
* normalize(), which reads from range_, and by normalizeToRange,
|
|
||||||
* which is public and can accept an arbitrary range from the caller.
|
|
||||||
*/
|
|
||||||
template <class T>
|
|
||||||
static void
|
|
||||||
normalize(
|
|
||||||
bool& negative,
|
|
||||||
T& mantissa,
|
|
||||||
int& exponent,
|
|
||||||
internalrep const& minMantissa,
|
|
||||||
internalrep const& maxMantissa);
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
friend void
|
|
||||||
doNormalize(
|
|
||||||
bool& negative,
|
|
||||||
T& mantissa_,
|
|
||||||
int& exponent_,
|
|
||||||
MantissaRange::rep const& minMantissa,
|
|
||||||
MantissaRange::rep const& maxMantissa);
|
|
||||||
|
|
||||||
bool
|
|
||||||
isnormal() const noexcept;
|
isnormal() const noexcept;
|
||||||
|
|
||||||
// Copy the number, but modify the exponent by "exponentDelta". Because the
|
|
||||||
// mantissa doesn't change, the result will be "mostly" normalized, but the
|
|
||||||
// exponent could go out of range, so it will be checked.
|
|
||||||
Number
|
|
||||||
shiftExponent(int exponentDelta) const;
|
|
||||||
|
|
||||||
// Safely convert rep (int64) mantissa to internalrep (uint64). If the rep
|
|
||||||
// is negative, returns the positive value. This takes a little extra work
|
|
||||||
// because converting std::numeric_limits<std::int64_t>::min() flirts with
|
|
||||||
// UB, and can vary across compilers.
|
|
||||||
static internalrep
|
|
||||||
externalToInternal(rep mantissa);
|
|
||||||
|
|
||||||
class Guard;
|
class Guard;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline constexpr Number::Number(
|
inline constexpr Number::Number(rep mantissa, int exponent, unchecked) noexcept
|
||||||
bool negative,
|
: mantissa_{mantissa}, exponent_{exponent}
|
||||||
internalrep mantissa,
|
|
||||||
int exponent,
|
|
||||||
unchecked) noexcept
|
|
||||||
: negative_(negative), mantissa_{mantissa}, exponent_{exponent}
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
inline constexpr Number::Number(
|
|
||||||
internalrep mantissa,
|
|
||||||
int exponent,
|
|
||||||
unchecked) noexcept
|
|
||||||
: Number(false, mantissa, exponent, unchecked{})
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr static Number numZero{};
|
|
||||||
|
|
||||||
inline Number::Number(
|
|
||||||
bool negative,
|
|
||||||
internalrep mantissa,
|
|
||||||
int exponent,
|
|
||||||
normalized)
|
|
||||||
: Number(negative, mantissa, exponent, unchecked{})
|
|
||||||
{
|
|
||||||
normalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Number::Number(internalrep mantissa, int exponent, normalized)
|
|
||||||
: Number(false, mantissa, exponent, normalized{})
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Number::Number(rep mantissa, int exponent)
|
inline Number::Number(rep mantissa, int exponent)
|
||||||
: Number(mantissa < 0, externalToInternal(mantissa), exponent, normalized{})
|
: mantissa_{mantissa}, exponent_{exponent}
|
||||||
{
|
{
|
||||||
|
normalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Number::Number(rep mantissa) : Number{mantissa, 0}
|
inline Number::Number(rep mantissa) : Number{mantissa, 0}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the mantissa of the external view of the Number.
|
|
||||||
*
|
|
||||||
* Please see the "---- External Interface ----" section of the class
|
|
||||||
* documentation for an explanation of why the internal value may be modified.
|
|
||||||
*/
|
|
||||||
inline constexpr Number::rep
|
inline constexpr Number::rep
|
||||||
Number::mantissa() const noexcept
|
Number::mantissa() const noexcept
|
||||||
{
|
{
|
||||||
auto m = mantissa_;
|
return mantissa_;
|
||||||
if (m > maxRep)
|
|
||||||
{
|
|
||||||
XRPL_ASSERT_PARTS(
|
|
||||||
!isnormal() || (m % 10 == 0 && m / 10 <= maxRep),
|
|
||||||
"ripple::Number::mantissa",
|
|
||||||
"large normalized mantissa has no remainder");
|
|
||||||
m /= 10;
|
|
||||||
}
|
|
||||||
auto const sign = negative_ ? -1 : 1;
|
|
||||||
return sign * static_cast<Number::rep>(m);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the exponent of the external view of the Number.
|
|
||||||
*
|
|
||||||
* Please see the "---- External Interface ----" section of the class
|
|
||||||
* documentation for an explanation of why the internal value may be modified.
|
|
||||||
*/
|
|
||||||
inline constexpr int
|
inline constexpr int
|
||||||
Number::exponent() const noexcept
|
Number::exponent() const noexcept
|
||||||
{
|
{
|
||||||
auto e = exponent_;
|
return exponent_;
|
||||||
if (mantissa_ > maxRep)
|
|
||||||
{
|
|
||||||
XRPL_ASSERT_PARTS(
|
|
||||||
!isnormal() || (mantissa_ % 10 == 0 && mantissa_ / 10 <= maxRep),
|
|
||||||
"ripple::Number::exponent",
|
|
||||||
"large normalized mantissa has no remainder");
|
|
||||||
++e;
|
|
||||||
}
|
|
||||||
return e;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline constexpr Number
|
inline constexpr Number
|
||||||
@@ -631,17 +247,15 @@ Number::operator+() const noexcept
|
|||||||
inline constexpr Number
|
inline constexpr Number
|
||||||
Number::operator-() const noexcept
|
Number::operator-() const noexcept
|
||||||
{
|
{
|
||||||
if (mantissa_ == 0)
|
|
||||||
return Number{};
|
|
||||||
auto x = *this;
|
auto x = *this;
|
||||||
x.negative_ = !x.negative_;
|
x.mantissa_ = -x.mantissa_;
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Number&
|
inline Number&
|
||||||
Number::operator++()
|
Number::operator++()
|
||||||
{
|
{
|
||||||
*this += one();
|
*this += Number{1000000000000000, -15, unchecked{}};
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -656,7 +270,7 @@ Number::operator++(int)
|
|||||||
inline Number&
|
inline Number&
|
||||||
Number::operator--()
|
Number::operator--()
|
||||||
{
|
{
|
||||||
*this -= one();
|
*this -= Number{1000000000000000, -15, unchecked{}};
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -706,54 +320,30 @@ operator/(Number const& x, Number const& y)
|
|||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Number
|
inline constexpr Number
|
||||||
Number::min() noexcept
|
Number::min() noexcept
|
||||||
{
|
{
|
||||||
return Number{false, range_.get().min, minExponent, unchecked{}};
|
return Number{minMantissa, minExponent, unchecked{}};
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Number
|
inline constexpr Number
|
||||||
Number::max() noexcept
|
Number::max() noexcept
|
||||||
{
|
{
|
||||||
return Number{
|
return Number{maxMantissa, maxExponent, unchecked{}};
|
||||||
false, std::min(range_.get().max, maxRep), maxExponent, unchecked{}};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Number
|
inline constexpr Number
|
||||||
Number::lowest() noexcept
|
Number::lowest() noexcept
|
||||||
{
|
{
|
||||||
return Number{
|
return -Number{maxMantissa, maxExponent, unchecked{}};
|
||||||
true, std::min(range_.get().max, maxRep), maxExponent, unchecked{}};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline constexpr bool
|
||||||
Number::isnormal() const noexcept
|
Number::isnormal() const noexcept
|
||||||
{
|
{
|
||||||
MantissaRange const& range = range_;
|
auto const abs_m = mantissa_ < 0 ? -mantissa_ : mantissa_;
|
||||||
auto const abs_m = mantissa_;
|
return minMantissa <= abs_m && abs_m <= maxMantissa &&
|
||||||
return *this == Number{} ||
|
minExponent <= exponent_ && exponent_ <= maxExponent;
|
||||||
(range.min <= abs_m && abs_m <= range.max &&
|
|
||||||
(abs_m <= maxRep || abs_m % 10 == 0) && minExponent <= exponent_ &&
|
|
||||||
exponent_ <= maxExponent);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <Integral64 T>
|
|
||||||
std::pair<T, int>
|
|
||||||
Number::normalizeToRange(T minMantissa, T maxMantissa) const
|
|
||||||
{
|
|
||||||
bool negative = negative_;
|
|
||||||
internalrep mantissa = mantissa_;
|
|
||||||
int exponent = exponent_;
|
|
||||||
|
|
||||||
if constexpr (std::is_unsigned_v<T>)
|
|
||||||
XRPL_ASSERT_PARTS(
|
|
||||||
!negative,
|
|
||||||
"ripple::Number::normalizeToRange",
|
|
||||||
"Number is non-negative for unsigned range.");
|
|
||||||
Number::normalize(negative, mantissa, exponent, minMantissa, maxMantissa);
|
|
||||||
|
|
||||||
auto const sign = negative ? -1 : 1;
|
|
||||||
return std::make_pair(static_cast<T>(sign * mantissa), exponent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline constexpr Number
|
inline constexpr Number
|
||||||
@@ -795,20 +385,6 @@ squelch(Number const& x, Number const& limit) noexcept
|
|||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::string
|
|
||||||
to_string(MantissaRange::mantissa_scale const& scale)
|
|
||||||
{
|
|
||||||
switch (scale)
|
|
||||||
{
|
|
||||||
case MantissaRange::small:
|
|
||||||
return "small";
|
|
||||||
case MantissaRange::large:
|
|
||||||
return "large";
|
|
||||||
default:
|
|
||||||
throw std::runtime_error("Bad scale");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class saveNumberRoundMode
|
class saveNumberRoundMode
|
||||||
{
|
{
|
||||||
Number::rounding_mode mode_;
|
Number::rounding_mode mode_;
|
||||||
@@ -847,34 +423,6 @@ public:
|
|||||||
operator=(NumberRoundModeGuard const&) = delete;
|
operator=(NumberRoundModeGuard const&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Sets the new scale and restores the old scale when it leaves scope.
|
|
||||||
*
|
|
||||||
* If you think you need to use this class outside of unit tests, no you don't.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class NumberMantissaScaleGuard
|
|
||||||
{
|
|
||||||
MantissaRange::mantissa_scale const saved_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit NumberMantissaScaleGuard(
|
|
||||||
MantissaRange::mantissa_scale scale) noexcept
|
|
||||||
: saved_{Number::getMantissaScale()}
|
|
||||||
{
|
|
||||||
Number::setMantissaScale(scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
~NumberMantissaScaleGuard()
|
|
||||||
{
|
|
||||||
Number::setMantissaScale(saved_);
|
|
||||||
}
|
|
||||||
|
|
||||||
NumberMantissaScaleGuard(NumberMantissaScaleGuard const&) = delete;
|
|
||||||
|
|
||||||
NumberMantissaScaleGuard&
|
|
||||||
operator=(NumberMantissaScaleGuard const&) = delete;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace ripple
|
} // namespace ripple
|
||||||
|
|
||||||
#endif // RIPPLE_BASICS_NUMBER_H_INCLUDED
|
#endif // RIPPLE_BASICS_NUMBER_H_INCLUDED
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
#include <xrpl/basics/Resolver.h>
|
#include <xrpl/basics/Resolver.h>
|
||||||
#include <xrpl/beast/utility/Journal.h>
|
#include <xrpl/beast/utility/Journal.h>
|
||||||
|
|
||||||
#include <boost/asio/io_service.hpp>
|
#include <boost/asio/io_context.hpp>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ public:
|
|||||||
explicit ResolverAsio() = default;
|
explicit ResolverAsio() = default;
|
||||||
|
|
||||||
static std::unique_ptr<ResolverAsio>
|
static std::unique_ptr<ResolverAsio>
|
||||||
New(boost::asio::io_service&, beast::Journal);
|
New(boost::asio::io_context&, beast::Journal);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ripple
|
} // namespace ripple
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ public:
|
|||||||
@param count the number of items the slab allocator can allocate; note
|
@param count the number of items the slab allocator can allocate; note
|
||||||
that a count of 0 is valid and means that the allocator
|
that a count of 0 is valid and means that the allocator
|
||||||
is, effectively, disabled. This can be very useful in some
|
is, effectively, disabled. This can be very useful in some
|
||||||
contexts (e.g. when minimal memory usage is needed) and
|
contexts (e.g. when mimimal memory usage is needed) and
|
||||||
allows for graceful failure.
|
allows for graceful failure.
|
||||||
*/
|
*/
|
||||||
constexpr explicit SlabAllocator(
|
constexpr explicit SlabAllocator(
|
||||||
|
|||||||
@@ -27,11 +27,9 @@
|
|||||||
#include <boost/utility/string_view.hpp>
|
#include <boost/utility/string_view.hpp>
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <concepts>
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
@@ -48,40 +46,28 @@ namespace ripple {
|
|||||||
std::string
|
std::string
|
||||||
sqlBlobLiteral(Blob const& blob);
|
sqlBlobLiteral(Blob const& blob);
|
||||||
|
|
||||||
namespace impl {
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
concept SomeChar = std::same_as<std::remove_cvref_t<T>, int8_t> ||
|
|
||||||
std::same_as<std::remove_cvref_t<T>, char> ||
|
|
||||||
std::same_as<std::remove_cvref_t<T>, uint8_t>;
|
|
||||||
|
|
||||||
inline constexpr std::array<std::optional<int>, 256> DIGIT_LOOKUP_TABLE = []() {
|
|
||||||
std::array<std::optional<int>, 256> t{};
|
|
||||||
|
|
||||||
for (int i = 0; i < 10; ++i)
|
|
||||||
t['0' + i] = i;
|
|
||||||
|
|
||||||
for (int i = 0; i < 6; ++i)
|
|
||||||
{
|
|
||||||
t['A' + i] = 10 + i;
|
|
||||||
t['a' + i] = 10 + i;
|
|
||||||
}
|
|
||||||
|
|
||||||
return t;
|
|
||||||
}();
|
|
||||||
|
|
||||||
inline std::optional<int>
|
|
||||||
hexCharToInt(SomeChar auto hexChar)
|
|
||||||
{
|
|
||||||
return DIGIT_LOOKUP_TABLE[static_cast<uint8_t>(hexChar)];
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace impl
|
|
||||||
|
|
||||||
template <class Iterator>
|
template <class Iterator>
|
||||||
std::optional<Blob>
|
std::optional<Blob>
|
||||||
strUnHex(std::size_t strSize, Iterator begin, Iterator end)
|
strUnHex(std::size_t strSize, Iterator begin, Iterator end)
|
||||||
{
|
{
|
||||||
|
static constexpr std::array<int, 256> const unxtab = []() {
|
||||||
|
std::array<int, 256> t{};
|
||||||
|
|
||||||
|
for (auto& x : t)
|
||||||
|
x = -1;
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; ++i)
|
||||||
|
t['0' + i] = i;
|
||||||
|
|
||||||
|
for (int i = 0; i < 6; ++i)
|
||||||
|
{
|
||||||
|
t['A' + i] = 10 + i;
|
||||||
|
t['a' + i] = 10 + i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}();
|
||||||
|
|
||||||
Blob out;
|
Blob out;
|
||||||
|
|
||||||
out.reserve((strSize + 1) / 2);
|
out.reserve((strSize + 1) / 2);
|
||||||
@@ -90,27 +76,27 @@ strUnHex(std::size_t strSize, Iterator begin, Iterator end)
|
|||||||
|
|
||||||
if (strSize & 1)
|
if (strSize & 1)
|
||||||
{
|
{
|
||||||
auto const c = impl::hexCharToInt(*iter++);
|
int c = unxtab[*iter++];
|
||||||
|
|
||||||
if (!c.has_value())
|
if (c < 0)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
out.push_back(static_cast<unsigned char>(*c));
|
out.push_back(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (iter != end)
|
while (iter != end)
|
||||||
{
|
{
|
||||||
auto const cHigh = impl::hexCharToInt(*iter++);
|
int cHigh = unxtab[*iter++];
|
||||||
|
|
||||||
if (!cHigh.has_value())
|
if (cHigh < 0)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
auto const cLow = impl::hexCharToInt(*iter++);
|
int cLow = unxtab[*iter++];
|
||||||
|
|
||||||
if (!cLow.has_value())
|
if (cLow < 0)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
out.push_back(static_cast<unsigned char>((*cHigh << 4) | *cLow));
|
out.push_back(static_cast<unsigned char>((cHigh << 4) | cLow));
|
||||||
}
|
}
|
||||||
|
|
||||||
return {std::move(out)};
|
return {std::move(out)};
|
||||||
|
|||||||
@@ -66,11 +66,6 @@ struct is_contiguous_container<Slice> : std::true_type
|
|||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename...>
|
|
||||||
struct always_false_t : std::bool_constant<false>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
/** Integers of any length that is a multiple of 32-bits
|
/** Integers of any length that is a multiple of 32-bits
|
||||||
@@ -297,31 +292,10 @@ public:
|
|||||||
std::is_trivially_copyable<typename Container::value_type>::value>>
|
std::is_trivially_copyable<typename Container::value_type>::value>>
|
||||||
explicit base_uint(Container const& c)
|
explicit base_uint(Container const& c)
|
||||||
{
|
{
|
||||||
// Use always_false_t so the static_assert condition is dependent
|
|
||||||
// and only triggers when this constructor template is instantiated.
|
|
||||||
static_assert(
|
|
||||||
detail::always_false_t<Container>::value,
|
|
||||||
"This constructor is not intended to be used and will be soon "
|
|
||||||
"removed. "
|
|
||||||
"Use base_uint::fromRaw instead.");
|
|
||||||
}
|
|
||||||
|
|
||||||
template <
|
|
||||||
class Container,
|
|
||||||
class = std::enable_if_t<
|
|
||||||
detail::is_contiguous_container<Container>::value &&
|
|
||||||
std::is_trivially_copyable<typename Container::value_type>::value>>
|
|
||||||
static base_uint
|
|
||||||
fromRaw(Container const& c)
|
|
||||||
{
|
|
||||||
base_uint result;
|
|
||||||
XRPL_ASSERT(
|
XRPL_ASSERT(
|
||||||
c.size() * sizeof(typename Container::value_type) == size(),
|
c.size() * sizeof(typename Container::value_type) == size(),
|
||||||
"xrpl::base_uint::fromRaw(Container auto) : input size match");
|
"ripple::base_uint::base_uint(Container auto) : input size match");
|
||||||
std::size_t const canCopy =
|
std::memcpy(data_.data(), c.data(), size());
|
||||||
std::min(size(), c.size() * sizeof(typename Container::value_type));
|
|
||||||
std::memcpy(result.data_.data(), c.data(), canCopy);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Container>
|
template <class Container>
|
||||||
@@ -591,7 +565,7 @@ operator<=>(base_uint<Bits, Tag> const& lhs, base_uint<Bits, Tag> const& rhs)
|
|||||||
// This comparison might seem wrong on a casual inspection because it
|
// This comparison might seem wrong on a casual inspection because it
|
||||||
// compares data internally stored as std::uint32_t byte-by-byte. But
|
// compares data internally stored as std::uint32_t byte-by-byte. But
|
||||||
// note that the underlying data is stored in big endian, even if the
|
// note that the underlying data is stored in big endian, even if the
|
||||||
// platform is little endian. This makes the comparison correct.
|
// plaform is little endian. This makes the comparison correct.
|
||||||
//
|
//
|
||||||
// FIXME: use std::lexicographical_compare_three_way once support is
|
// FIXME: use std::lexicographical_compare_three_way once support is
|
||||||
// added to MacOS.
|
// added to MacOS.
|
||||||
@@ -658,16 +632,6 @@ to_string(base_uint<Bits, Tag> const& a)
|
|||||||
return strHex(a.cbegin(), a.cend());
|
return strHex(a.cbegin(), a.cend());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <std::size_t Bits, class Tag>
|
|
||||||
inline std::string
|
|
||||||
to_short_string(base_uint<Bits, Tag> const& a)
|
|
||||||
{
|
|
||||||
static_assert(
|
|
||||||
base_uint<Bits, Tag>::bytes > 4,
|
|
||||||
"For 4 bytes or less, use a native type");
|
|
||||||
return strHex(a.cbegin(), a.cbegin() + 4) + "...";
|
|
||||||
}
|
|
||||||
|
|
||||||
template <std::size_t Bits, class Tag>
|
template <std::size_t Bits, class Tag>
|
||||||
inline std::ostream&
|
inline std::ostream&
|
||||||
operator<<(std::ostream& out, base_uint<Bits, Tag> const& u)
|
operator<<(std::ostream& out, base_uint<Bits, Tag> const& u)
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ namespace ripple {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* MSVC 2019 version 16.9.0 added [[nodiscard]] to the std comparison
|
* MSVC 2019 version 16.9.0 added [[nodiscard]] to the std comparison
|
||||||
* operator() functions. boost::bimap checks that the comparator is a
|
* operator() functions. boost::bimap checks that the comparitor is a
|
||||||
* BinaryFunction, in part by calling the function and ignoring the value.
|
* BinaryFunction, in part by calling the function and ignoring the value.
|
||||||
* These two things don't play well together. These wrapper classes simply
|
* These two things don't play well together. These wrapper classes simply
|
||||||
* strip [[nodiscard]] from operator() for use in boost::bimap.
|
* strip [[nodiscard]] from operator() for use in boost::bimap.
|
||||||
|
|||||||
@@ -28,8 +28,9 @@ namespace ripple {
|
|||||||
// the destination can hold all values of the source. This is particularly
|
// the destination can hold all values of the source. This is particularly
|
||||||
// handy when the source or destination is an enumeration type.
|
// handy when the source or destination is an enumeration type.
|
||||||
|
|
||||||
template <class Src, class Dest>
|
template <class Dest, class Src>
|
||||||
concept SafeToCast = (std::is_integral_v<Src> && std::is_integral_v<Dest>) &&
|
static constexpr bool is_safetocasttovalue_v =
|
||||||
|
(std::is_integral_v<Src> && std::is_integral_v<Dest>) &&
|
||||||
(std::is_signed<Src>::value || std::is_unsigned<Dest>::value) &&
|
(std::is_signed<Src>::value || std::is_unsigned<Dest>::value) &&
|
||||||
(std::is_signed<Src>::value != std::is_signed<Dest>::value
|
(std::is_signed<Src>::value != std::is_signed<Dest>::value
|
||||||
? sizeof(Dest) > sizeof(Src)
|
? sizeof(Dest) > sizeof(Src)
|
||||||
@@ -77,7 +78,7 @@ inline constexpr std::
|
|||||||
unsafe_cast(Src s) noexcept
|
unsafe_cast(Src s) noexcept
|
||||||
{
|
{
|
||||||
static_assert(
|
static_assert(
|
||||||
!SafeToCast<Src, Dest>,
|
!is_safetocasttovalue_v<Dest, Src>,
|
||||||
"Only unsafe if casting signed to unsigned or "
|
"Only unsafe if casting signed to unsigned or "
|
||||||
"destination is too small");
|
"destination is too small");
|
||||||
return static_cast<Dest>(s);
|
return static_cast<Dest>(s);
|
||||||
|
|||||||
@@ -23,7 +23,8 @@
|
|||||||
#include <xrpl/beast/utility/instrumentation.h>
|
#include <xrpl/beast/utility/instrumentation.h>
|
||||||
|
|
||||||
#include <boost/asio/basic_waitable_timer.hpp>
|
#include <boost/asio/basic_waitable_timer.hpp>
|
||||||
#include <boost/asio/io_service.hpp>
|
#include <boost/asio/io_context.hpp>
|
||||||
|
#include <boost/asio/post.hpp>
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
@@ -32,7 +33,7 @@
|
|||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
/** Measures handler latency on an io_service queue. */
|
/** Measures handler latency on an io_context queue. */
|
||||||
template <class Clock>
|
template <class Clock>
|
||||||
class io_latency_probe
|
class io_latency_probe
|
||||||
{
|
{
|
||||||
@@ -44,12 +45,12 @@ private:
|
|||||||
std::condition_variable_any m_cond;
|
std::condition_variable_any m_cond;
|
||||||
std::size_t m_count;
|
std::size_t m_count;
|
||||||
duration const m_period;
|
duration const m_period;
|
||||||
boost::asio::io_service& m_ios;
|
boost::asio::io_context& m_ios;
|
||||||
boost::asio::basic_waitable_timer<std::chrono::steady_clock> m_timer;
|
boost::asio::basic_waitable_timer<std::chrono::steady_clock> m_timer;
|
||||||
bool m_cancel;
|
bool m_cancel;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
io_latency_probe(duration const& period, boost::asio::io_service& ios)
|
io_latency_probe(duration const& period, boost::asio::io_context& ios)
|
||||||
: m_count(1)
|
: m_count(1)
|
||||||
, m_period(period)
|
, m_period(period)
|
||||||
, m_ios(ios)
|
, m_ios(ios)
|
||||||
@@ -64,16 +65,16 @@ public:
|
|||||||
cancel(lock, true);
|
cancel(lock, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return the io_service associated with the latency probe. */
|
/** Return the io_context associated with the latency probe. */
|
||||||
/** @{ */
|
/** @{ */
|
||||||
boost::asio::io_service&
|
boost::asio::io_context&
|
||||||
get_io_service()
|
get_io_context()
|
||||||
{
|
{
|
||||||
return m_ios;
|
return m_ios;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::asio::io_service const&
|
boost::asio::io_context const&
|
||||||
get_io_service() const
|
get_io_context() const
|
||||||
{
|
{
|
||||||
return m_ios;
|
return m_ios;
|
||||||
}
|
}
|
||||||
@@ -109,8 +110,10 @@ public:
|
|||||||
std::lock_guard lock(m_mutex);
|
std::lock_guard lock(m_mutex);
|
||||||
if (m_cancel)
|
if (m_cancel)
|
||||||
throw std::logic_error("io_latency_probe is canceled");
|
throw std::logic_error("io_latency_probe is canceled");
|
||||||
m_ios.post(sample_op<Handler>(
|
boost::asio::post(
|
||||||
std::forward<Handler>(handler), Clock::now(), false, this));
|
m_ios,
|
||||||
|
sample_op<Handler>(
|
||||||
|
std::forward<Handler>(handler), Clock::now(), false, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Initiate continuous i/o latency sampling.
|
/** Initiate continuous i/o latency sampling.
|
||||||
@@ -124,8 +127,10 @@ public:
|
|||||||
std::lock_guard lock(m_mutex);
|
std::lock_guard lock(m_mutex);
|
||||||
if (m_cancel)
|
if (m_cancel)
|
||||||
throw std::logic_error("io_latency_probe is canceled");
|
throw std::logic_error("io_latency_probe is canceled");
|
||||||
m_ios.post(sample_op<Handler>(
|
boost::asio::post(
|
||||||
std::forward<Handler>(handler), Clock::now(), true, this));
|
m_ios,
|
||||||
|
sample_op<Handler>(
|
||||||
|
std::forward<Handler>(handler), Clock::now(), true, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -236,12 +241,13 @@ private:
|
|||||||
// The latency is too high to maintain the desired
|
// The latency is too high to maintain the desired
|
||||||
// period so don't bother with a timer.
|
// period so don't bother with a timer.
|
||||||
//
|
//
|
||||||
m_probe->m_ios.post(
|
boost::asio::post(
|
||||||
|
m_probe->m_ios,
|
||||||
sample_op<Handler>(m_handler, now, m_repeat, m_probe));
|
sample_op<Handler>(m_handler, now, m_repeat, m_probe));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_probe->m_timer.expires_from_now(when - now);
|
m_probe->m_timer.expires_after(when - now);
|
||||||
m_probe->m_timer.async_wait(
|
m_probe->m_timer.async_wait(
|
||||||
sample_op<Handler>(m_handler, now, m_repeat, m_probe));
|
sample_op<Handler>(m_handler, now, m_repeat, m_probe));
|
||||||
}
|
}
|
||||||
@@ -254,7 +260,8 @@ private:
|
|||||||
if (!m_probe)
|
if (!m_probe)
|
||||||
return;
|
return;
|
||||||
typename Clock::time_point const now(Clock::now());
|
typename Clock::time_point const now(Clock::now());
|
||||||
m_probe->m_ios.post(
|
boost::asio::post(
|
||||||
|
m_probe->m_ios,
|
||||||
sample_op<Handler>(m_handler, now, m_repeat, m_probe));
|
sample_op<Handler>(m_handler, now, m_repeat, m_probe));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ template <
|
|||||||
class Allocator = std::allocator<Key>>
|
class Allocator = std::allocator<Key>>
|
||||||
using aged_multiset = detail::
|
using aged_multiset = detail::
|
||||||
aged_ordered_container<true, false, Key, void, Clock, Compare, Allocator>;
|
aged_ordered_container<true, false, Key, void, Clock, Compare, Allocator>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ using aged_unordered_map = detail::aged_unordered_container<
|
|||||||
Hash,
|
Hash,
|
||||||
KeyEqual,
|
KeyEqual,
|
||||||
Allocator>;
|
Allocator>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ using aged_unordered_multimap = detail::aged_unordered_container<
|
|||||||
Hash,
|
Hash,
|
||||||
KeyEqual,
|
KeyEqual,
|
||||||
Allocator>;
|
Allocator>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ using aged_unordered_set = detail::aged_unordered_container<
|
|||||||
Hash,
|
Hash,
|
||||||
KeyEqual,
|
KeyEqual,
|
||||||
Allocator>;
|
Allocator>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -24,8 +24,6 @@
|
|||||||
#ifndef BEAST_CORE_CURRENT_THREAD_NAME_H_INCLUDED
|
#ifndef BEAST_CORE_CURRENT_THREAD_NAME_H_INCLUDED
|
||||||
#define BEAST_CORE_CURRENT_THREAD_NAME_H_INCLUDED
|
#define BEAST_CORE_CURRENT_THREAD_NAME_H_INCLUDED
|
||||||
|
|
||||||
#include <boost/predef.h>
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
@@ -37,31 +35,6 @@ namespace beast {
|
|||||||
void
|
void
|
||||||
setCurrentThreadName(std::string_view newThreadName);
|
setCurrentThreadName(std::string_view newThreadName);
|
||||||
|
|
||||||
#if BOOST_OS_LINUX
|
|
||||||
|
|
||||||
// On Linux, thread names are limited to 16 bytes including the null terminator.
|
|
||||||
// Maximum number of characters is therefore 15.
|
|
||||||
constexpr std::size_t maxThreadNameLength = 15;
|
|
||||||
|
|
||||||
/** Sets the name of the caller thread with compile-time size checking.
|
|
||||||
@tparam N The size of the string literal including null terminator
|
|
||||||
@param newThreadName A string literal to set as the thread name
|
|
||||||
|
|
||||||
This template overload enforces that thread names are at most 16 characters
|
|
||||||
(including null terminator) at compile time, matching Linux's limit.
|
|
||||||
*/
|
|
||||||
template <std::size_t N>
|
|
||||||
void
|
|
||||||
setCurrentThreadName(char const (&newThreadName)[N])
|
|
||||||
{
|
|
||||||
static_assert(
|
|
||||||
N <= maxThreadNameLength + 1,
|
|
||||||
"Thread name cannot exceed 15 characters");
|
|
||||||
|
|
||||||
setCurrentThreadName(std::string_view(newThreadName, N - 1));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Returns the name of the caller thread.
|
/** Returns the name of the caller thread.
|
||||||
|
|
||||||
The name returned is the name as set by a call to setCurrentThreadName().
|
The name returned is the name as set by a call to setCurrentThreadName().
|
||||||
|
|||||||
@@ -94,11 +94,7 @@ hash_append(Hasher& h, beast::IP::Address const& addr) noexcept
|
|||||||
else if (addr.is_v6())
|
else if (addr.is_v6())
|
||||||
hash_append(h, addr.to_v6().to_bytes());
|
hash_append(h, addr.to_v6().to_bytes());
|
||||||
else
|
else
|
||||||
{
|
|
||||||
// LCOV_EXCL_START
|
|
||||||
UNREACHABLE("beast::hash_append : invalid address type");
|
UNREACHABLE("beast::hash_append : invalid address type");
|
||||||
// LCOV_EXCL_STOP
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} // namespace beast
|
} // namespace beast
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,11 @@
|
|||||||
#ifndef BEAST_TEST_YIELD_TO_HPP
|
#ifndef BEAST_TEST_YIELD_TO_HPP
|
||||||
#define BEAST_TEST_YIELD_TO_HPP
|
#define BEAST_TEST_YIELD_TO_HPP
|
||||||
|
|
||||||
#include <boost/asio/io_service.hpp>
|
#include <boost/asio/executor_work_guard.hpp>
|
||||||
|
#include <boost/asio/io_context.hpp>
|
||||||
#include <boost/asio/spawn.hpp>
|
#include <boost/asio/spawn.hpp>
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
|
#include <boost/thread/csbl/memory/allocator_arg.hpp>
|
||||||
|
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
@@ -29,10 +31,12 @@ namespace test {
|
|||||||
class enable_yield_to
|
class enable_yield_to
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
boost::asio::io_service ios_;
|
boost::asio::io_context ios_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
boost::optional<boost::asio::io_service::work> work_;
|
boost::optional<boost::asio::executor_work_guard<
|
||||||
|
boost::asio::io_context::executor_type>>
|
||||||
|
work_;
|
||||||
std::vector<std::thread> threads_;
|
std::vector<std::thread> threads_;
|
||||||
std::mutex m_;
|
std::mutex m_;
|
||||||
std::condition_variable cv_;
|
std::condition_variable cv_;
|
||||||
@@ -42,7 +46,8 @@ public:
|
|||||||
/// The type of yield context passed to functions.
|
/// The type of yield context passed to functions.
|
||||||
using yield_context = boost::asio::yield_context;
|
using yield_context = boost::asio::yield_context;
|
||||||
|
|
||||||
explicit enable_yield_to(std::size_t concurrency = 1) : work_(ios_)
|
explicit enable_yield_to(std::size_t concurrency = 1)
|
||||||
|
: work_(boost::asio::make_work_guard(ios_))
|
||||||
{
|
{
|
||||||
threads_.reserve(concurrency);
|
threads_.reserve(concurrency);
|
||||||
while (concurrency--)
|
while (concurrency--)
|
||||||
@@ -56,9 +61,9 @@ public:
|
|||||||
t.join();
|
t.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the `io_service` associated with the object
|
/// Return the `io_context` associated with the object
|
||||||
boost::asio::io_service&
|
boost::asio::io_context&
|
||||||
get_io_service()
|
get_io_context()
|
||||||
{
|
{
|
||||||
return ios_;
|
return ios_;
|
||||||
}
|
}
|
||||||
@@ -111,13 +116,18 @@ enable_yield_to::spawn(F0&& f, FN&&... fn)
|
|||||||
{
|
{
|
||||||
boost::asio::spawn(
|
boost::asio::spawn(
|
||||||
ios_,
|
ios_,
|
||||||
|
boost::allocator_arg,
|
||||||
|
boost::context::fixedsize_stack(2 * 1024 * 1024),
|
||||||
[&](yield_context yield) {
|
[&](yield_context yield) {
|
||||||
f(yield);
|
f(yield);
|
||||||
std::lock_guard lock{m_};
|
std::lock_guard lock{m_};
|
||||||
if (--running_ == 0)
|
if (--running_ == 0)
|
||||||
cv_.notify_all();
|
cv_.notify_all();
|
||||||
},
|
},
|
||||||
boost::coroutines::attributes(2 * 1024 * 1024));
|
[](std::exception_ptr e) {
|
||||||
|
if (e)
|
||||||
|
std::rethrow_exception(e);
|
||||||
|
});
|
||||||
spawn(fn...);
|
spawn(fn...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ public:
|
|||||||
|
|
||||||
The argument string is available to suites and
|
The argument string is available to suites and
|
||||||
allows for customization of the test. Each suite
|
allows for customization of the test. Each suite
|
||||||
defines its own syntax for the argument string.
|
defines its own syntax for the argumnet string.
|
||||||
The same argument is passed to all suites.
|
The same argument is passed to all suites.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -32,23 +32,18 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||||||
// The duplication is because Visual Studio 2019 cannot compile that header
|
// The duplication is because Visual Studio 2019 cannot compile that header
|
||||||
// even with the option -Zc:__cplusplus added.
|
// even with the option -Zc:__cplusplus added.
|
||||||
#define ALWAYS(cond, message, ...) assert((message) && (cond))
|
#define ALWAYS(cond, message, ...) assert((message) && (cond))
|
||||||
#define ALWAYS_OR_UNREACHABLE(cond, message) assert((message) && (cond))
|
#define ALWAYS_OR_UNREACHABLE(cond, message, ...) assert((message) && (cond))
|
||||||
#define SOMETIMES(cond, message, ...)
|
#define SOMETIMES(cond, message, ...)
|
||||||
#define REACHABLE(message, ...)
|
#define REACHABLE(message, ...)
|
||||||
#define UNREACHABLE(message, ...) assert((message) && false)
|
#define UNREACHABLE(message, ...) assert((message) && false)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define XRPL_ASSERT ALWAYS_OR_UNREACHABLE
|
#define XRPL_ASSERT ALWAYS_OR_UNREACHABLE
|
||||||
#define XRPL_ASSERT_PARTS(cond, function, description, ...) \
|
|
||||||
XRPL_ASSERT(cond, function " : " description)
|
|
||||||
|
|
||||||
// How to use the instrumentation macros:
|
// How to use the instrumentation macros:
|
||||||
//
|
//
|
||||||
// * XRPL_ASSERT if cond must be true but the line might not be reached during
|
// * XRPL_ASSERT if cond must be true but the line might not be reached during
|
||||||
// fuzzing. Same like `assert` in normal use.
|
// fuzzing. Same like `assert` in normal use.
|
||||||
// * XRPL_ASSERT_PARTS is for convenience, and works like XRPL_ASSERT, but
|
|
||||||
// splits the message param into "function" and "description", then joins
|
|
||||||
// them with " : " before passing to XRPL_ASSERT.
|
|
||||||
// * ALWAYS if cond must be true _and_ the line must be reached during fuzzing.
|
// * ALWAYS if cond must be true _and_ the line must be reached during fuzzing.
|
||||||
// Same like `assert` in normal use.
|
// Same like `assert` in normal use.
|
||||||
// * REACHABLE if the line must be reached during fuzzing
|
// * REACHABLE if the line must be reached during fuzzing
|
||||||
|
|||||||
@@ -217,7 +217,7 @@ Reader::parse(Value& root, BufferSequence const& bs)
|
|||||||
std::string s;
|
std::string s;
|
||||||
s.reserve(buffer_size(bs));
|
s.reserve(buffer_size(bs));
|
||||||
for (auto const& b : bs)
|
for (auto const& b : bs)
|
||||||
s.append(buffer_cast<char const*>(b), buffer_size(b));
|
s.append(static_cast<char const*>(b.data()), buffer_size(b));
|
||||||
return parse(s, root);
|
return parse(s, root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,6 @@
|
|||||||
#include <xrpl/json/json_forwards.h>
|
#include <xrpl/json/json_forwards.h>
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <limits>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -159,9 +158,9 @@ public:
|
|||||||
using ArrayIndex = UInt;
|
using ArrayIndex = UInt;
|
||||||
|
|
||||||
static Value const null;
|
static Value const null;
|
||||||
static constexpr Int minInt = std::numeric_limits<Int>::min();
|
static Int const minInt;
|
||||||
static constexpr Int maxInt = std::numeric_limits<Int>::max();
|
static Int const maxInt;
|
||||||
static constexpr UInt maxUInt = std::numeric_limits<UInt>::max();
|
static UInt const maxUInt;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class CZString
|
class CZString
|
||||||
@@ -264,10 +263,6 @@ public:
|
|||||||
bool
|
bool
|
||||||
asBool() const;
|
asBool() const;
|
||||||
|
|
||||||
/** Correct absolute value from int or unsigned int */
|
|
||||||
UInt
|
|
||||||
asAbsUInt() const;
|
|
||||||
|
|
||||||
// TODO: What is the "empty()" method this docstring mentions?
|
// TODO: What is the "empty()" method this docstring mentions?
|
||||||
/** isNull() tests to see if this field is null. Don't use this method to
|
/** isNull() tests to see if this field is null. Don't use this method to
|
||||||
test for emptiness: use empty(). */
|
test for emptiness: use empty(). */
|
||||||
@@ -400,9 +395,6 @@ public:
|
|||||||
/// Return true if the object has a member named key.
|
/// Return true if the object has a member named key.
|
||||||
bool
|
bool
|
||||||
isMember(std::string const& key) const;
|
isMember(std::string const& key) const;
|
||||||
/// Return true if the object has a member named key.
|
|
||||||
bool
|
|
||||||
isMember(StaticString const& key) const;
|
|
||||||
|
|
||||||
/// \brief Return a list of the member names.
|
/// \brief Return a list of the member names.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ public:
|
|||||||
* without formatting (not human friendly).
|
* without formatting (not human friendly).
|
||||||
*
|
*
|
||||||
* The JSON document is written in a single line. It is not intended for 'human'
|
* 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 bandwidth
|
* consumption, but may be useful to support feature such as RPC where bandwith
|
||||||
* is limited. \sa Reader, Value
|
* is limited. \sa Reader, Value
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
AutoSocket(
|
AutoSocket(
|
||||||
boost::asio::io_service& s,
|
boost::asio::io_context& s,
|
||||||
boost::asio::ssl::context& c,
|
boost::asio::ssl::context& c,
|
||||||
bool secureOnly,
|
bool secureOnly,
|
||||||
bool plainOnly)
|
bool plainOnly)
|
||||||
@@ -58,7 +58,7 @@ public:
|
|||||||
mSocket = std::make_unique<ssl_socket>(s, c);
|
mSocket = std::make_unique<ssl_socket>(s, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoSocket(boost::asio::io_service& s, boost::asio::ssl::context& c)
|
AutoSocket(boost::asio::io_context& s, boost::asio::ssl::context& c)
|
||||||
: AutoSocket(s, c, false, false)
|
: AutoSocket(s, c, false, false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -156,7 +156,7 @@ public:
|
|||||||
{
|
{
|
||||||
lowest_layer().shutdown(plain_socket::shutdown_both);
|
lowest_layer().shutdown(plain_socket::shutdown_both);
|
||||||
}
|
}
|
||||||
catch (boost::system::system_error const& e)
|
catch (boost::system::system_error& e)
|
||||||
{
|
{
|
||||||
ec = e.code();
|
ec = e.code();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
#include <xrpl/basics/ByteUtilities.h>
|
#include <xrpl/basics/ByteUtilities.h>
|
||||||
#include <xrpl/beast/utility/Journal.h>
|
#include <xrpl/beast/utility/Journal.h>
|
||||||
|
|
||||||
#include <boost/asio/io_service.hpp>
|
#include <boost/asio/io_context.hpp>
|
||||||
#include <boost/asio/streambuf.hpp>
|
#include <boost/asio/streambuf.hpp>
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
@@ -51,7 +51,7 @@ public:
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
get(bool bSSL,
|
get(bool bSSL,
|
||||||
boost::asio::io_service& io_service,
|
boost::asio::io_context& io_context,
|
||||||
std::deque<std::string> deqSites,
|
std::deque<std::string> deqSites,
|
||||||
unsigned short const port,
|
unsigned short const port,
|
||||||
std::string const& strPath,
|
std::string const& strPath,
|
||||||
@@ -65,7 +65,7 @@ public:
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
get(bool bSSL,
|
get(bool bSSL,
|
||||||
boost::asio::io_service& io_service,
|
boost::asio::io_context& io_context,
|
||||||
std::string strSite,
|
std::string strSite,
|
||||||
unsigned short const port,
|
unsigned short const port,
|
||||||
std::string const& strPath,
|
std::string const& strPath,
|
||||||
@@ -80,7 +80,7 @@ public:
|
|||||||
static void
|
static void
|
||||||
request(
|
request(
|
||||||
bool bSSL,
|
bool bSSL,
|
||||||
boost::asio::io_service& io_service,
|
boost::asio::io_context& io_context,
|
||||||
std::string strSite,
|
std::string strSite,
|
||||||
unsigned short const port,
|
unsigned short const port,
|
||||||
std::function<
|
std::function<
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ public:
|
|||||||
{
|
{
|
||||||
strm.set_verify_callback(
|
strm.set_verify_callback(
|
||||||
std::bind(
|
std::bind(
|
||||||
&rfc2818_verify,
|
&rfc6125_verify,
|
||||||
host,
|
host,
|
||||||
std::placeholders::_1,
|
std::placeholders::_1,
|
||||||
std::placeholders::_2,
|
std::placeholders::_2,
|
||||||
@@ -167,7 +167,7 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief callback invoked for name verification - just passes through
|
* @brief callback invoked for name verification - just passes through
|
||||||
* to the asio rfc2818 implementation.
|
* to the asio `host_name_verification` (rfc6125) implementation.
|
||||||
*
|
*
|
||||||
* @param domain hostname expected
|
* @param domain hostname expected
|
||||||
* @param preverified passed by implementation
|
* @param preverified passed by implementation
|
||||||
@@ -175,13 +175,13 @@ public:
|
|||||||
* @param j journal for logging
|
* @param j journal for logging
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
rfc2818_verify(
|
rfc6125_verify(
|
||||||
std::string const& domain,
|
std::string const& domain,
|
||||||
bool preverified,
|
bool preverified,
|
||||||
boost::asio::ssl::verify_context& ctx,
|
boost::asio::ssl::verify_context& ctx,
|
||||||
beast::Journal j)
|
beast::Journal j)
|
||||||
{
|
{
|
||||||
if (boost::asio::ssl::rfc2818_verification(domain)(preverified, ctx))
|
if (boost::asio::ssl::host_name_verification(domain)(preverified, ctx))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
JLOG(j.warn()) << "Outbound SSL connection to " << domain
|
JLOG(j.warn()) << "Outbound SSL connection to " << domain
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ toAmount(
|
|||||||
{
|
{
|
||||||
if (isXRP(issue))
|
if (isXRP(issue))
|
||||||
return STAmount(issue, static_cast<std::int64_t>(n));
|
return STAmount(issue, static_cast<std::int64_t>(n));
|
||||||
return STAmount(issue, n);
|
return STAmount(issue, n.mantissa(), n.exponent());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -100,27 +100,7 @@ public:
|
|||||||
bool
|
bool
|
||||||
native() const
|
native() const
|
||||||
{
|
{
|
||||||
return std::visit(
|
return holds<Issue>() && get<Issue>().native();
|
||||||
[&]<ValidIssueType TIss>(TIss const& issue) {
|
|
||||||
if constexpr (std::is_same_v<TIss, Issue>)
|
|
||||||
return issue.native();
|
|
||||||
if constexpr (std::is_same_v<TIss, MPTIssue>)
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
issue_);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
integral() const
|
|
||||||
{
|
|
||||||
return std::visit(
|
|
||||||
[&]<ValidIssueType TIss>(TIss const& issue) {
|
|
||||||
if constexpr (std::is_same_v<TIss, Issue>)
|
|
||||||
return issue.native();
|
|
||||||
if constexpr (std::is_same_v<TIss, MPTIssue>)
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
issue_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
friend constexpr bool
|
friend constexpr bool
|
||||||
|
|||||||
565
include/xrpl/protocol/FeeUnits.h
Normal file
565
include/xrpl/protocol/FeeUnits.h
Normal file
@@ -0,0 +1,565 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
This file is part of rippled: https://github.com/ripple/rippled
|
||||||
|
Copyright (c) 2019 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 BASICS_FEES_H_INCLUDED
|
||||||
|
#define BASICS_FEES_H_INCLUDED
|
||||||
|
|
||||||
|
#include <xrpl/basics/safe_cast.h>
|
||||||
|
#include <xrpl/beast/utility/Zero.h>
|
||||||
|
#include <xrpl/beast/utility/instrumentation.h>
|
||||||
|
#include <xrpl/json/json_value.h>
|
||||||
|
|
||||||
|
#include <boost/multiprecision/cpp_int.hpp>
|
||||||
|
#include <boost/operators.hpp>
|
||||||
|
|
||||||
|
#include <iosfwd>
|
||||||
|
#include <limits>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
namespace ripple {
|
||||||
|
|
||||||
|
namespace feeunit {
|
||||||
|
|
||||||
|
/** "drops" are the smallest divisible amount of XRP. This is what most
|
||||||
|
of the code uses. */
|
||||||
|
struct dropTag;
|
||||||
|
/** "fee units" calculations are a not-really-unitless value that is used
|
||||||
|
to express the cost of a given transaction vs. a reference transaction.
|
||||||
|
They are primarily used by the Transactor classes. */
|
||||||
|
struct feeunitTag;
|
||||||
|
/** "fee levels" are used by the transaction queue to compare the relative
|
||||||
|
cost of transactions that require different levels of effort to process.
|
||||||
|
See also: src/ripple/app/misc/FeeEscalation.md#fee-level */
|
||||||
|
struct feelevelTag;
|
||||||
|
/** unitless values are plain scalars wrapped in a TaggedFee. They are
|
||||||
|
used for calculations in this header. */
|
||||||
|
struct unitlessTag;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
using enable_if_unit_t = typename std::enable_if_t<
|
||||||
|
std::is_class_v<T> && std::is_object_v<typename T::unit_type> &&
|
||||||
|
std::is_object_v<typename T::value_type>>;
|
||||||
|
|
||||||
|
/** `is_usable_unit_v` is checked to ensure that only values with
|
||||||
|
known valid type tags can be used (sometimes transparently) in
|
||||||
|
non-fee contexts. At the time of implementation, this includes
|
||||||
|
all known tags, but more may be added in the future, and they
|
||||||
|
should not be added automatically unless determined to be
|
||||||
|
appropriate.
|
||||||
|
*/
|
||||||
|
template <class T, class = enable_if_unit_t<T>>
|
||||||
|
constexpr bool is_usable_unit_v =
|
||||||
|
std::is_same_v<typename T::unit_type, feeunitTag> ||
|
||||||
|
std::is_same_v<typename T::unit_type, feelevelTag> ||
|
||||||
|
std::is_same_v<typename T::unit_type, unitlessTag> ||
|
||||||
|
std::is_same_v<typename T::unit_type, dropTag>;
|
||||||
|
|
||||||
|
template <class UnitTag, class T>
|
||||||
|
class TaggedFee : private boost::totally_ordered<TaggedFee<UnitTag, T>>,
|
||||||
|
private boost::additive<TaggedFee<UnitTag, T>>,
|
||||||
|
private boost::equality_comparable<TaggedFee<UnitTag, T>, T>,
|
||||||
|
private boost::dividable<TaggedFee<UnitTag, T>, T>,
|
||||||
|
private boost::modable<TaggedFee<UnitTag, T>, T>,
|
||||||
|
private boost::unit_steppable<TaggedFee<UnitTag, T>>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using unit_type = UnitTag;
|
||||||
|
using value_type = T;
|
||||||
|
|
||||||
|
private:
|
||||||
|
value_type fee_;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
template <class Other>
|
||||||
|
static constexpr bool is_compatible_v =
|
||||||
|
std::is_arithmetic_v<Other> && std::is_arithmetic_v<value_type> &&
|
||||||
|
std::is_convertible_v<Other, value_type>;
|
||||||
|
|
||||||
|
template <class OtherFee, class = enable_if_unit_t<OtherFee>>
|
||||||
|
static constexpr bool is_compatiblefee_v =
|
||||||
|
is_compatible_v<typename OtherFee::value_type> &&
|
||||||
|
std::is_same_v<UnitTag, typename OtherFee::unit_type>;
|
||||||
|
|
||||||
|
template <class Other>
|
||||||
|
using enable_if_compatible_t =
|
||||||
|
typename std::enable_if_t<is_compatible_v<Other>>;
|
||||||
|
|
||||||
|
template <class OtherFee>
|
||||||
|
using enable_if_compatiblefee_t =
|
||||||
|
typename std::enable_if_t<is_compatiblefee_v<OtherFee>>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
TaggedFee() = default;
|
||||||
|
constexpr TaggedFee(TaggedFee const& other) = default;
|
||||||
|
constexpr TaggedFee&
|
||||||
|
operator=(TaggedFee const& other) = default;
|
||||||
|
|
||||||
|
constexpr explicit TaggedFee(beast::Zero) : fee_(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr TaggedFee&
|
||||||
|
operator=(beast::Zero)
|
||||||
|
{
|
||||||
|
fee_ = 0;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr explicit TaggedFee(value_type fee) : fee_(fee)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
TaggedFee&
|
||||||
|
operator=(value_type fee)
|
||||||
|
{
|
||||||
|
fee_ = fee;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Instances with the same unit, and a type that is
|
||||||
|
"safe" to convert to this one can be converted
|
||||||
|
implicitly */
|
||||||
|
template <
|
||||||
|
class Other,
|
||||||
|
class = std::enable_if_t<
|
||||||
|
is_compatible_v<Other> &&
|
||||||
|
is_safetocasttovalue_v<value_type, Other>>>
|
||||||
|
constexpr TaggedFee(TaggedFee<unit_type, Other> const& fee)
|
||||||
|
: TaggedFee(safe_cast<value_type>(fee.fee()))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr TaggedFee
|
||||||
|
operator*(value_type const& rhs) const
|
||||||
|
{
|
||||||
|
return TaggedFee{fee_ * rhs};
|
||||||
|
}
|
||||||
|
|
||||||
|
friend constexpr TaggedFee
|
||||||
|
operator*(value_type lhs, TaggedFee const& rhs)
|
||||||
|
{
|
||||||
|
// multiplication is commutative
|
||||||
|
return rhs * lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr value_type
|
||||||
|
operator/(TaggedFee const& rhs) const
|
||||||
|
{
|
||||||
|
return fee_ / rhs.fee_;
|
||||||
|
}
|
||||||
|
|
||||||
|
TaggedFee&
|
||||||
|
operator+=(TaggedFee const& other)
|
||||||
|
{
|
||||||
|
fee_ += other.fee();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TaggedFee&
|
||||||
|
operator-=(TaggedFee const& other)
|
||||||
|
{
|
||||||
|
fee_ -= other.fee();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TaggedFee&
|
||||||
|
operator++()
|
||||||
|
{
|
||||||
|
++fee_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TaggedFee&
|
||||||
|
operator--()
|
||||||
|
{
|
||||||
|
--fee_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TaggedFee&
|
||||||
|
operator*=(value_type const& rhs)
|
||||||
|
{
|
||||||
|
fee_ *= rhs;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TaggedFee&
|
||||||
|
operator/=(value_type const& rhs)
|
||||||
|
{
|
||||||
|
fee_ /= rhs;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class transparent = value_type>
|
||||||
|
std::enable_if_t<std::is_integral_v<transparent>, TaggedFee&>
|
||||||
|
operator%=(value_type const& rhs)
|
||||||
|
{
|
||||||
|
fee_ %= rhs;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TaggedFee
|
||||||
|
operator-() const
|
||||||
|
{
|
||||||
|
static_assert(
|
||||||
|
std::is_signed_v<T>, "- operator illegal on unsigned fee types");
|
||||||
|
return TaggedFee{-fee_};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
operator==(TaggedFee const& other) const
|
||||||
|
{
|
||||||
|
return fee_ == other.fee_;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Other, class = enable_if_compatible_t<Other>>
|
||||||
|
bool
|
||||||
|
operator==(TaggedFee<unit_type, Other> const& other) const
|
||||||
|
{
|
||||||
|
return fee_ == other.fee();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
operator==(value_type other) const
|
||||||
|
{
|
||||||
|
return fee_ == other;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Other, class = enable_if_compatible_t<Other>>
|
||||||
|
bool
|
||||||
|
operator!=(TaggedFee<unit_type, Other> const& other) const
|
||||||
|
{
|
||||||
|
return !operator==(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
operator<(TaggedFee const& other) const
|
||||||
|
{
|
||||||
|
return fee_ < other.fee_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns true if the amount is not zero */
|
||||||
|
explicit constexpr
|
||||||
|
operator bool() const noexcept
|
||||||
|
{
|
||||||
|
return fee_ != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Return the sign of the amount */
|
||||||
|
constexpr int
|
||||||
|
signum() const noexcept
|
||||||
|
{
|
||||||
|
return (fee_ < 0) ? -1 : (fee_ ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the number of drops */
|
||||||
|
constexpr value_type
|
||||||
|
fee() const
|
||||||
|
{
|
||||||
|
return fee_;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Other>
|
||||||
|
constexpr double
|
||||||
|
decimalFromReference(TaggedFee<unit_type, Other> reference) const
|
||||||
|
{
|
||||||
|
return static_cast<double>(fee_) / reference.fee();
|
||||||
|
}
|
||||||
|
|
||||||
|
// `is_usable_unit_v` is checked to ensure that only values with
|
||||||
|
// known valid type tags can be converted to JSON. At the time
|
||||||
|
// of implementation, that includes all known tags, but more may
|
||||||
|
// be added in the future.
|
||||||
|
std::enable_if_t<is_usable_unit_v<TaggedFee>, Json::Value>
|
||||||
|
jsonClipped() const
|
||||||
|
{
|
||||||
|
if constexpr (std::is_integral_v<value_type>)
|
||||||
|
{
|
||||||
|
using jsontype = std::conditional_t<
|
||||||
|
std::is_signed_v<value_type>,
|
||||||
|
Json::Int,
|
||||||
|
Json::UInt>;
|
||||||
|
|
||||||
|
constexpr auto min = std::numeric_limits<jsontype>::min();
|
||||||
|
constexpr auto max = std::numeric_limits<jsontype>::max();
|
||||||
|
|
||||||
|
if (fee_ < min)
|
||||||
|
return min;
|
||||||
|
if (fee_ > max)
|
||||||
|
return max;
|
||||||
|
return static_cast<jsontype>(fee_);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return fee_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the underlying value. Code SHOULD NOT call this
|
||||||
|
function unless the type has been abstracted away,
|
||||||
|
e.g. in a templated function.
|
||||||
|
*/
|
||||||
|
constexpr value_type
|
||||||
|
value() const
|
||||||
|
{
|
||||||
|
return fee_;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend std::istream&
|
||||||
|
operator>>(std::istream& s, TaggedFee& val)
|
||||||
|
{
|
||||||
|
s >> val.fee_;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Output Fees as just their numeric value.
|
||||||
|
template <class Char, class Traits, class UnitTag, class T>
|
||||||
|
std::basic_ostream<Char, Traits>&
|
||||||
|
operator<<(std::basic_ostream<Char, Traits>& os, TaggedFee<UnitTag, T> const& q)
|
||||||
|
{
|
||||||
|
return os << q.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class UnitTag, class T>
|
||||||
|
std::string
|
||||||
|
to_string(TaggedFee<UnitTag, T> const& amount)
|
||||||
|
{
|
||||||
|
return std::to_string(amount.fee());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Source, class = enable_if_unit_t<Source>>
|
||||||
|
constexpr bool can_muldiv_source_v =
|
||||||
|
std::is_convertible_v<typename Source::value_type, std::uint64_t>;
|
||||||
|
|
||||||
|
template <class Dest, class = enable_if_unit_t<Dest>>
|
||||||
|
constexpr bool can_muldiv_dest_v =
|
||||||
|
can_muldiv_source_v<Dest> && // Dest is also a source
|
||||||
|
std::is_convertible_v<std::uint64_t, typename Dest::value_type> &&
|
||||||
|
sizeof(typename Dest::value_type) >= sizeof(std::uint64_t);
|
||||||
|
|
||||||
|
template <
|
||||||
|
class Source1,
|
||||||
|
class Source2,
|
||||||
|
class = enable_if_unit_t<Source1>,
|
||||||
|
class = enable_if_unit_t<Source2>>
|
||||||
|
constexpr bool can_muldiv_sources_v =
|
||||||
|
can_muldiv_source_v<Source1> && can_muldiv_source_v<Source2> &&
|
||||||
|
std::is_same_v<typename Source1::unit_type, typename Source2::unit_type>;
|
||||||
|
|
||||||
|
template <
|
||||||
|
class Source1,
|
||||||
|
class Source2,
|
||||||
|
class Dest,
|
||||||
|
class = enable_if_unit_t<Source1>,
|
||||||
|
class = enable_if_unit_t<Source2>,
|
||||||
|
class = enable_if_unit_t<Dest>>
|
||||||
|
constexpr bool can_muldiv_v =
|
||||||
|
can_muldiv_sources_v<Source1, Source2> && can_muldiv_dest_v<Dest>;
|
||||||
|
// Source and Dest can be the same by default
|
||||||
|
|
||||||
|
template <
|
||||||
|
class Source1,
|
||||||
|
class Source2,
|
||||||
|
class Dest,
|
||||||
|
class = enable_if_unit_t<Source1>,
|
||||||
|
class = enable_if_unit_t<Source2>,
|
||||||
|
class = enable_if_unit_t<Dest>>
|
||||||
|
constexpr bool can_muldiv_commute_v = can_muldiv_v<Source1, Source2, Dest> &&
|
||||||
|
!std::is_same_v<typename Source1::unit_type, typename Dest::unit_type>;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
using enable_muldiv_source_t =
|
||||||
|
typename std::enable_if_t<can_muldiv_source_v<T>>;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
using enable_muldiv_dest_t = typename std::enable_if_t<can_muldiv_dest_v<T>>;
|
||||||
|
|
||||||
|
template <class Source1, class Source2>
|
||||||
|
using enable_muldiv_sources_t =
|
||||||
|
typename std::enable_if_t<can_muldiv_sources_v<Source1, Source2>>;
|
||||||
|
|
||||||
|
template <class Source1, class Source2, class Dest>
|
||||||
|
using enable_muldiv_t =
|
||||||
|
typename std::enable_if_t<can_muldiv_v<Source1, Source2, Dest>>;
|
||||||
|
|
||||||
|
template <class Source1, class Source2, class Dest>
|
||||||
|
using enable_muldiv_commute_t =
|
||||||
|
typename std::enable_if_t<can_muldiv_commute_v<Source1, Source2, Dest>>;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
TaggedFee<unitlessTag, T>
|
||||||
|
scalar(T value)
|
||||||
|
{
|
||||||
|
return TaggedFee<unitlessTag, T>{value};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <
|
||||||
|
class Source1,
|
||||||
|
class Source2,
|
||||||
|
class Dest,
|
||||||
|
class = enable_muldiv_t<Source1, Source2, Dest>>
|
||||||
|
std::optional<Dest>
|
||||||
|
mulDivU(Source1 value, Dest mul, Source2 div)
|
||||||
|
{
|
||||||
|
// Fees can never be negative in any context.
|
||||||
|
if (value.value() < 0 || mul.value() < 0 || div.value() < 0)
|
||||||
|
{
|
||||||
|
// split the asserts so if one hits, the user can tell which
|
||||||
|
// without a debugger.
|
||||||
|
XRPL_ASSERT(
|
||||||
|
value.value() >= 0,
|
||||||
|
"ripple::feeunit::mulDivU : minimum value input");
|
||||||
|
XRPL_ASSERT(
|
||||||
|
mul.value() >= 0, "ripple::feeunit::mulDivU : minimum mul input");
|
||||||
|
XRPL_ASSERT(
|
||||||
|
div.value() >= 0, "ripple::feeunit::mulDivU : minimum div input");
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
using desttype = typename Dest::value_type;
|
||||||
|
constexpr auto max = std::numeric_limits<desttype>::max();
|
||||||
|
|
||||||
|
// Shortcuts, since these happen a lot in the real world
|
||||||
|
if (value == div)
|
||||||
|
return mul;
|
||||||
|
if (mul.value() == div.value())
|
||||||
|
{
|
||||||
|
if (value.value() > max)
|
||||||
|
return std::nullopt;
|
||||||
|
return Dest{static_cast<desttype>(value.value())};
|
||||||
|
}
|
||||||
|
|
||||||
|
using namespace boost::multiprecision;
|
||||||
|
|
||||||
|
uint128_t product;
|
||||||
|
product = multiply(
|
||||||
|
product,
|
||||||
|
static_cast<std::uint64_t>(value.value()),
|
||||||
|
static_cast<std::uint64_t>(mul.value()));
|
||||||
|
|
||||||
|
auto quotient = product / div.value();
|
||||||
|
|
||||||
|
if (quotient > max)
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
|
return Dest{static_cast<desttype>(quotient)};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace feeunit
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
using FeeLevel = feeunit::TaggedFee<feeunit::feelevelTag, T>;
|
||||||
|
using FeeLevel64 = FeeLevel<std::uint64_t>;
|
||||||
|
using FeeLevelDouble = FeeLevel<double>;
|
||||||
|
|
||||||
|
template <
|
||||||
|
class Source1,
|
||||||
|
class Source2,
|
||||||
|
class Dest,
|
||||||
|
class = feeunit::enable_muldiv_t<Source1, Source2, Dest>>
|
||||||
|
std::optional<Dest>
|
||||||
|
mulDiv(Source1 value, Dest mul, Source2 div)
|
||||||
|
{
|
||||||
|
return feeunit::mulDivU(value, mul, div);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <
|
||||||
|
class Source1,
|
||||||
|
class Source2,
|
||||||
|
class Dest,
|
||||||
|
class = feeunit::enable_muldiv_commute_t<Source1, Source2, Dest>>
|
||||||
|
std::optional<Dest>
|
||||||
|
mulDiv(Dest value, Source1 mul, Source2 div)
|
||||||
|
{
|
||||||
|
// Multiplication is commutative
|
||||||
|
return feeunit::mulDivU(mul, value, div);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Dest, class = feeunit::enable_muldiv_dest_t<Dest>>
|
||||||
|
std::optional<Dest>
|
||||||
|
mulDiv(std::uint64_t value, Dest mul, std::uint64_t div)
|
||||||
|
{
|
||||||
|
// Give the scalars a non-tag so the
|
||||||
|
// unit-handling version gets called.
|
||||||
|
return feeunit::mulDivU(feeunit::scalar(value), mul, feeunit::scalar(div));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Dest, class = feeunit::enable_muldiv_dest_t<Dest>>
|
||||||
|
std::optional<Dest>
|
||||||
|
mulDiv(Dest value, std::uint64_t mul, std::uint64_t div)
|
||||||
|
{
|
||||||
|
// Multiplication is commutative
|
||||||
|
return mulDiv(mul, value, div);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <
|
||||||
|
class Source1,
|
||||||
|
class Source2,
|
||||||
|
class = feeunit::enable_muldiv_sources_t<Source1, Source2>>
|
||||||
|
std::optional<std::uint64_t>
|
||||||
|
mulDiv(Source1 value, std::uint64_t mul, Source2 div)
|
||||||
|
{
|
||||||
|
// Give the scalars a dimensionless unit so the
|
||||||
|
// unit-handling version gets called.
|
||||||
|
auto unitresult = feeunit::mulDivU(value, feeunit::scalar(mul), div);
|
||||||
|
|
||||||
|
if (!unitresult)
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
|
return unitresult->value();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <
|
||||||
|
class Source1,
|
||||||
|
class Source2,
|
||||||
|
class = feeunit::enable_muldiv_sources_t<Source1, Source2>>
|
||||||
|
std::optional<std::uint64_t>
|
||||||
|
mulDiv(std::uint64_t value, Source1 mul, Source2 div)
|
||||||
|
{
|
||||||
|
// Multiplication is commutative
|
||||||
|
return mulDiv(mul, value, div);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Dest, class Src>
|
||||||
|
constexpr std::enable_if_t<
|
||||||
|
std::is_same_v<typename Dest::unit_type, typename Src::unit_type> &&
|
||||||
|
std::is_integral_v<typename Dest::value_type> &&
|
||||||
|
std::is_integral_v<typename Src::value_type>,
|
||||||
|
Dest>
|
||||||
|
safe_cast(Src s) noexcept
|
||||||
|
{
|
||||||
|
// Dest may not have an explicit value constructor
|
||||||
|
return Dest{safe_cast<typename Dest::value_type>(s.value())};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Dest, class Src>
|
||||||
|
constexpr std::enable_if_t<
|
||||||
|
std::is_same_v<typename Dest::unit_type, typename Src::unit_type> &&
|
||||||
|
std::is_integral_v<typename Dest::value_type> &&
|
||||||
|
std::is_integral_v<typename Src::value_type>,
|
||||||
|
Dest>
|
||||||
|
unsafe_cast(Src s) noexcept
|
||||||
|
{
|
||||||
|
// Dest may not have an explicit value constructor
|
||||||
|
return Dest{unsafe_cast<typename Dest::value_type>(s.value())};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ripple
|
||||||
|
|
||||||
|
#endif // BASICS_FEES_H_INCLUDED
|
||||||
@@ -45,10 +45,8 @@ class IOUAmount : private boost::totally_ordered<IOUAmount>,
|
|||||||
private boost::additive<IOUAmount>
|
private boost::additive<IOUAmount>
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
using mantissa_type = std::int64_t;
|
std::int64_t mantissa_;
|
||||||
using exponent_type = int;
|
int exponent_;
|
||||||
mantissa_type mantissa_;
|
|
||||||
exponent_type exponent_;
|
|
||||||
|
|
||||||
/** Adjusts the mantissa and exponent to the proper range.
|
/** Adjusts the mantissa and exponent to the proper range.
|
||||||
|
|
||||||
@@ -59,14 +57,11 @@ private:
|
|||||||
void
|
void
|
||||||
normalize();
|
normalize();
|
||||||
|
|
||||||
static IOUAmount
|
|
||||||
fromNumber(Number const& number);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IOUAmount() = default;
|
IOUAmount() = default;
|
||||||
explicit IOUAmount(Number const& other);
|
explicit IOUAmount(Number const& other);
|
||||||
IOUAmount(beast::Zero);
|
IOUAmount(beast::Zero);
|
||||||
IOUAmount(mantissa_type mantissa, exponent_type exponent);
|
IOUAmount(std::int64_t mantissa, int exponent);
|
||||||
|
|
||||||
IOUAmount& operator=(beast::Zero);
|
IOUAmount& operator=(beast::Zero);
|
||||||
|
|
||||||
@@ -95,10 +90,10 @@ public:
|
|||||||
int
|
int
|
||||||
signum() const noexcept;
|
signum() const noexcept;
|
||||||
|
|
||||||
exponent_type
|
int
|
||||||
exponent() const noexcept;
|
exponent() const noexcept;
|
||||||
|
|
||||||
mantissa_type
|
std::int64_t
|
||||||
mantissa() const noexcept;
|
mantissa() const noexcept;
|
||||||
|
|
||||||
static IOUAmount
|
static IOUAmount
|
||||||
@@ -116,7 +111,7 @@ inline IOUAmount::IOUAmount(beast::Zero)
|
|||||||
*this = beast::zero;
|
*this = beast::zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline IOUAmount::IOUAmount(mantissa_type mantissa, exponent_type exponent)
|
inline IOUAmount::IOUAmount(std::int64_t mantissa, int exponent)
|
||||||
: mantissa_(mantissa), exponent_(exponent)
|
: mantissa_(mantissa), exponent_(exponent)
|
||||||
{
|
{
|
||||||
normalize();
|
normalize();
|
||||||
@@ -173,13 +168,13 @@ IOUAmount::signum() const noexcept
|
|||||||
return (mantissa_ < 0) ? -1 : (mantissa_ ? 1 : 0);
|
return (mantissa_ < 0) ? -1 : (mantissa_ ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline IOUAmount::exponent_type
|
inline int
|
||||||
IOUAmount::exponent() const noexcept
|
IOUAmount::exponent() const noexcept
|
||||||
{
|
{
|
||||||
return exponent_;
|
return exponent_;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline IOUAmount::mantissa_type
|
inline std::int64_t
|
||||||
IOUAmount::mantissa() const noexcept
|
IOUAmount::mantissa() const noexcept
|
||||||
{
|
{
|
||||||
return mantissa_;
|
return mantissa_;
|
||||||
|
|||||||
@@ -287,11 +287,9 @@ delegate(AccountID const& account, AccountID const& authorizedAccount) noexcept;
|
|||||||
Keylet
|
Keylet
|
||||||
bridge(STXChainBridge const& bridge, STXChainBridge::ChainType chainType);
|
bridge(STXChainBridge const& bridge, STXChainBridge::ChainType chainType);
|
||||||
|
|
||||||
// `seq` is stored as `sfXChainClaimID` in the object
|
|
||||||
Keylet
|
Keylet
|
||||||
xChainClaimID(STXChainBridge const& bridge, std::uint64_t seq);
|
xChainClaimID(STXChainBridge const& bridge, std::uint64_t seq);
|
||||||
|
|
||||||
// `seq` is stored as `sfXChainAccountCreateCount` in the object
|
|
||||||
Keylet
|
Keylet
|
||||||
xChainCreateAccountClaimID(STXChainBridge const& bridge, std::uint64_t seq);
|
xChainCreateAccountClaimID(STXChainBridge const& bridge, std::uint64_t seq);
|
||||||
|
|
||||||
@@ -346,29 +344,24 @@ vault(uint256 const& vaultKey)
|
|||||||
return {ltVAULT, vaultKey};
|
return {ltVAULT, vaultKey};
|
||||||
}
|
}
|
||||||
|
|
||||||
Keylet
|
|
||||||
loanbroker(AccountID const& owner, std::uint32_t seq) noexcept;
|
|
||||||
|
|
||||||
inline Keylet
|
|
||||||
loanbroker(uint256 const& key)
|
|
||||||
{
|
|
||||||
return {ltLOAN_BROKER, key};
|
|
||||||
}
|
|
||||||
|
|
||||||
Keylet
|
|
||||||
loan(uint256 const& loanBrokerID, std::uint32_t loanSeq) noexcept;
|
|
||||||
|
|
||||||
inline Keylet
|
|
||||||
loan(uint256 const& key)
|
|
||||||
{
|
|
||||||
return {ltLOAN, key};
|
|
||||||
}
|
|
||||||
|
|
||||||
Keylet
|
Keylet
|
||||||
permissionedDomain(AccountID const& account, std::uint32_t seq) noexcept;
|
permissionedDomain(AccountID const& account, std::uint32_t seq) noexcept;
|
||||||
|
|
||||||
Keylet
|
Keylet
|
||||||
permissionedDomain(uint256 const& domainID) noexcept;
|
permissionedDomain(uint256 const& domainID) noexcept;
|
||||||
|
|
||||||
|
Keylet
|
||||||
|
subscription(
|
||||||
|
AccountID const& account,
|
||||||
|
AccountID const& dest,
|
||||||
|
std::uint32_t const& seq) noexcept;
|
||||||
|
|
||||||
|
inline Keylet
|
||||||
|
subscription(uint256 const& key) noexcept
|
||||||
|
{
|
||||||
|
return {ltSUBSCRIPTION, key};
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace keylet
|
} // namespace keylet
|
||||||
|
|
||||||
// Everything below is deprecated and should be removed in favor of keylets:
|
// Everything below is deprecated and should be removed in favor of keylets:
|
||||||
|
|||||||
@@ -56,9 +56,6 @@ public:
|
|||||||
bool
|
bool
|
||||||
native() const;
|
native() const;
|
||||||
|
|
||||||
bool
|
|
||||||
integral() const;
|
|
||||||
|
|
||||||
friend constexpr std::weak_ordering
|
friend constexpr std::weak_ordering
|
||||||
operator<=>(Issue const& lhs, Issue const& rhs);
|
operator<=>(Issue const& lhs, Issue const& rhs);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -56,13 +56,12 @@ enum LedgerEntryType : std::uint16_t
|
|||||||
#pragma push_macro("LEDGER_ENTRY")
|
#pragma push_macro("LEDGER_ENTRY")
|
||||||
#undef LEDGER_ENTRY
|
#undef LEDGER_ENTRY
|
||||||
|
|
||||||
#define LEDGER_ENTRY(tag, value, ...) tag = value,
|
#define LEDGER_ENTRY(tag, value, name, rpcName, fields) tag = value,
|
||||||
|
|
||||||
#include <xrpl/protocol/detail/ledger_entries.macro>
|
#include <xrpl/protocol/detail/ledger_entries.macro>
|
||||||
|
|
||||||
#undef LEDGER_ENTRY
|
#undef LEDGER_ENTRY
|
||||||
#pragma pop_macro("LEDGER_ENTRY")
|
#pragma pop_macro("LEDGER_ENTRY")
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
/** A special type, matching any ledger entry type.
|
/** A special type, matching any ledger entry type.
|
||||||
|
|
||||||
@@ -188,15 +187,6 @@ enum LedgerSpecificFlags {
|
|||||||
lsfMPTCanTransfer = 0x00000020,
|
lsfMPTCanTransfer = 0x00000020,
|
||||||
lsfMPTCanClawback = 0x00000040,
|
lsfMPTCanClawback = 0x00000040,
|
||||||
|
|
||||||
lsmfMPTCanMutateCanLock = 0x00000002,
|
|
||||||
lsmfMPTCanMutateRequireAuth = 0x00000004,
|
|
||||||
lsmfMPTCanMutateCanEscrow = 0x00000008,
|
|
||||||
lsmfMPTCanMutateCanTrade = 0x00000010,
|
|
||||||
lsmfMPTCanMutateCanTransfer = 0x00000020,
|
|
||||||
lsmfMPTCanMutateCanClawback = 0x00000040,
|
|
||||||
lsmfMPTCanMutateMetadata = 0x00010000,
|
|
||||||
lsmfMPTCanMutateTransferFee = 0x00020000,
|
|
||||||
|
|
||||||
// ltMPTOKEN
|
// ltMPTOKEN
|
||||||
lsfMPTAuthorized = 0x00000002,
|
lsfMPTAuthorized = 0x00000002,
|
||||||
|
|
||||||
@@ -205,11 +195,6 @@ enum LedgerSpecificFlags {
|
|||||||
|
|
||||||
// ltVAULT
|
// ltVAULT
|
||||||
lsfVaultPrivate = 0x00010000,
|
lsfVaultPrivate = 0x00010000,
|
||||||
|
|
||||||
// ltLOAN
|
|
||||||
lsfLoanDefault = 0x00010000,
|
|
||||||
lsfLoanImpaired = 0x00020000,
|
|
||||||
lsfLoanOverpayment = 0x00040000, // True, loan allows overpayments
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -65,12 +65,6 @@ public:
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
integral() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr bool
|
constexpr bool
|
||||||
|
|||||||
@@ -20,8 +20,6 @@
|
|||||||
#ifndef RIPPLE_PROTOCOL_PERMISSION_H_INCLUDED
|
#ifndef RIPPLE_PROTOCOL_PERMISSION_H_INCLUDED
|
||||||
#define RIPPLE_PROTOCOL_PERMISSION_H_INCLUDED
|
#define RIPPLE_PROTOCOL_PERMISSION_H_INCLUDED
|
||||||
|
|
||||||
#include <xrpl/protocol/Rules.h>
|
|
||||||
#include <xrpl/protocol/TER.h>
|
|
||||||
#include <xrpl/protocol/TxFormats.h>
|
#include <xrpl/protocol/TxFormats.h>
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
@@ -55,8 +53,6 @@ class Permission
|
|||||||
private:
|
private:
|
||||||
Permission();
|
Permission();
|
||||||
|
|
||||||
std::unordered_map<std::uint16_t, uint256> txFeatureMap_;
|
|
||||||
|
|
||||||
std::unordered_map<std::uint16_t, Delegation> delegatableTx_;
|
std::unordered_map<std::uint16_t, Delegation> delegatableTx_;
|
||||||
|
|
||||||
std::unordered_map<std::string, GranularPermissionType>
|
std::unordered_map<std::string, GranularPermissionType>
|
||||||
@@ -74,9 +70,6 @@ public:
|
|||||||
Permission&
|
Permission&
|
||||||
operator=(Permission const&) = delete;
|
operator=(Permission const&) = delete;
|
||||||
|
|
||||||
std::optional<std::string>
|
|
||||||
getPermissionName(std::uint32_t const value) const;
|
|
||||||
|
|
||||||
std::optional<std::uint32_t>
|
std::optional<std::uint32_t>
|
||||||
getGranularValue(std::string const& name) const;
|
getGranularValue(std::string const& name) const;
|
||||||
|
|
||||||
@@ -86,12 +79,8 @@ public:
|
|||||||
std::optional<TxType>
|
std::optional<TxType>
|
||||||
getGranularTxType(GranularPermissionType const& gpType) const;
|
getGranularTxType(GranularPermissionType const& gpType) const;
|
||||||
|
|
||||||
std::optional<std::reference_wrapper<uint256 const>> const
|
|
||||||
getTxFeature(TxType txType) const;
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
isDelegatable(std::uint32_t const& permissionValue, Rules const& rules)
|
isDelegatable(std::uint32_t const& permissionValue) const;
|
||||||
const;
|
|
||||||
|
|
||||||
// for tx level permission, permission value is equal to tx type plus one
|
// for tx level permission, permission value is equal to tx type plus one
|
||||||
uint32_t
|
uint32_t
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#include <xrpl/basics/ByteUtilities.h>
|
#include <xrpl/basics/ByteUtilities.h>
|
||||||
#include <xrpl/basics/base_uint.h>
|
#include <xrpl/basics/base_uint.h>
|
||||||
#include <xrpl/protocol/Units.h>
|
#include <xrpl/basics/partitioned_unordered_map.h>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
@@ -56,10 +56,7 @@ std::size_t constexpr oversizeMetaDataCap = 5200;
|
|||||||
/** The maximum number of entries per directory page */
|
/** The maximum number of entries per directory page */
|
||||||
std::size_t constexpr dirNodeMaxEntries = 32;
|
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;
|
std::uint64_t constexpr dirNodeMaxPages = 262144;
|
||||||
|
|
||||||
/** The maximum number of items in an NFT page */
|
/** The maximum number of items in an NFT page */
|
||||||
@@ -85,140 +82,6 @@ std::size_t constexpr maxDeletableTokenOfferEntries = 500;
|
|||||||
*/
|
*/
|
||||||
std::uint16_t constexpr maxTransferFee = 50000;
|
std::uint16_t constexpr maxTransferFee = 50000;
|
||||||
|
|
||||||
/** There are 10,000 basis points (bips) in 100%.
|
|
||||||
*
|
|
||||||
* Basis points represent 0.01%.
|
|
||||||
*
|
|
||||||
* Given a value X, to find the amount for B bps,
|
|
||||||
* use X * B / bipsPerUnity
|
|
||||||
*
|
|
||||||
* Example: If a loan broker has 999 XRP of debt, and must maintain 1,000 bps of
|
|
||||||
* that debt as cover (10%), then the minimum cover amount is 999,000,000 drops
|
|
||||||
* * 1000 / bipsPerUnity = 99,900,00 drops or 99.9 XRP.
|
|
||||||
*
|
|
||||||
* Given a percentage P, to find the number of bps that percentage represents,
|
|
||||||
* use P * bipsPerUnity.
|
|
||||||
*
|
|
||||||
* Example: 50% is 0.50 * bipsPerUnity = 5,000 bps.
|
|
||||||
*/
|
|
||||||
Bips32 constexpr bipsPerUnity(100 * 100);
|
|
||||||
static_assert(bipsPerUnity == Bips32{10'000});
|
|
||||||
TenthBips32 constexpr tenthBipsPerUnity(bipsPerUnity.value() * 10);
|
|
||||||
static_assert(tenthBipsPerUnity == TenthBips32(100'000));
|
|
||||||
|
|
||||||
constexpr Bips32
|
|
||||||
percentageToBips(std::uint32_t percentage)
|
|
||||||
{
|
|
||||||
return Bips32(percentage * bipsPerUnity.value() / 100);
|
|
||||||
}
|
|
||||||
constexpr TenthBips32
|
|
||||||
percentageToTenthBips(std::uint32_t percentage)
|
|
||||||
{
|
|
||||||
return TenthBips32(percentage * tenthBipsPerUnity.value() / 100);
|
|
||||||
}
|
|
||||||
template <typename T, class TBips>
|
|
||||||
constexpr T
|
|
||||||
bipsOfValue(T value, Bips<TBips> bips)
|
|
||||||
{
|
|
||||||
return value * bips.value() / bipsPerUnity.value();
|
|
||||||
}
|
|
||||||
template <typename T, class TBips>
|
|
||||||
constexpr T
|
|
||||||
tenthBipsOfValue(T value, TenthBips<TBips> bips)
|
|
||||||
{
|
|
||||||
return value * bips.value() / tenthBipsPerUnity.value();
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Lending {
|
|
||||||
/** The maximum management fee rate allowed by a loan broker in 1/10 bips.
|
|
||||||
|
|
||||||
Valid values are between 0 and 10% inclusive.
|
|
||||||
*/
|
|
||||||
TenthBips16 constexpr maxManagementFeeRate(
|
|
||||||
unsafe_cast<std::uint16_t>(percentageToTenthBips(10).value()));
|
|
||||||
static_assert(maxManagementFeeRate == TenthBips16(std::uint16_t(10'000u)));
|
|
||||||
|
|
||||||
/** The maximum coverage rate required of a loan broker in 1/10 bips.
|
|
||||||
|
|
||||||
Valid values are between 0 and 100% inclusive.
|
|
||||||
*/
|
|
||||||
TenthBips32 constexpr maxCoverRate = percentageToTenthBips(100);
|
|
||||||
static_assert(maxCoverRate == TenthBips32(100'000u));
|
|
||||||
|
|
||||||
/** The maximum overpayment fee on a loan in 1/10 bips.
|
|
||||||
*
|
|
||||||
Valid values are between 0 and 100% inclusive.
|
|
||||||
*/
|
|
||||||
TenthBips32 constexpr maxOverpaymentFee = percentageToTenthBips(100);
|
|
||||||
static_assert(maxOverpaymentFee == TenthBips32(100'000u));
|
|
||||||
|
|
||||||
/** Annualized interest rate of the Loan in 1/10 bips.
|
|
||||||
*
|
|
||||||
* Valid values are between 0 and 100% inclusive.
|
|
||||||
*/
|
|
||||||
TenthBips32 constexpr maxInterestRate = percentageToTenthBips(100);
|
|
||||||
static_assert(maxInterestRate == TenthBips32(100'000u));
|
|
||||||
|
|
||||||
/** The maximum premium added to the interest rate for late payments on a loan
|
|
||||||
* in 1/10 bips.
|
|
||||||
*
|
|
||||||
* Valid values are between 0 and 100% inclusive.
|
|
||||||
*/
|
|
||||||
TenthBips32 constexpr maxLateInterestRate = percentageToTenthBips(100);
|
|
||||||
static_assert(maxLateInterestRate == TenthBips32(100'000u));
|
|
||||||
|
|
||||||
/** The maximum close interest rate charged for repaying a loan early in 1/10
|
|
||||||
* bips.
|
|
||||||
*
|
|
||||||
* Valid values are between 0 and 100% inclusive.
|
|
||||||
*/
|
|
||||||
TenthBips32 constexpr maxCloseInterestRate = percentageToTenthBips(100);
|
|
||||||
static_assert(maxCloseInterestRate == TenthBips32(100'000u));
|
|
||||||
|
|
||||||
/** The maximum overpayment interest rate charged on loan overpayments in 1/10
|
|
||||||
* bips.
|
|
||||||
*
|
|
||||||
* Valid values are between 0 and 100% inclusive.
|
|
||||||
*/
|
|
||||||
TenthBips32 constexpr maxOverpaymentInterestRate = percentageToTenthBips(100);
|
|
||||||
static_assert(maxOverpaymentInterestRate == TenthBips32(100'000u));
|
|
||||||
|
|
||||||
/** LoanPay transaction cost will be one base fee per X combined payments
|
|
||||||
*
|
|
||||||
* The number of payments is estimated based on the Amount paid and the Loan's
|
|
||||||
* Fixed Payment size. Overpayments (indicated with the tfLoanOverpayment flag)
|
|
||||||
* count as one more payment.
|
|
||||||
*
|
|
||||||
* This number was chosen arbitrarily, but should not be changed once released
|
|
||||||
* without an amendment
|
|
||||||
*/
|
|
||||||
static constexpr int loanPaymentsPerFeeIncrement = 5;
|
|
||||||
|
|
||||||
/** Maximum number of combined payments that a LoanPay transaction will process
|
|
||||||
*
|
|
||||||
* This limit is enforced during the loan payment process, and thus is not
|
|
||||||
* estimated. If the limit is hit, no further payments or overpayments will be
|
|
||||||
* processed, no matter how much of the transation Amount is left, but the
|
|
||||||
* transaction will succeed with the payments that have been processed up to
|
|
||||||
* that point.
|
|
||||||
*
|
|
||||||
* This limit is independent of loanPaymentsPerFeeIncrement, so a transaction
|
|
||||||
* could potentially be charged for many more payments than actually get
|
|
||||||
* processed. Users should take care not to submit a transaction paying more
|
|
||||||
* than loanMaximumPaymentsPerTransaction * Loan.PeriodicPayment. Because
|
|
||||||
* overpayments are charged as a payment, if submitting
|
|
||||||
* loanMaximumPaymentsPerTransaction * Loan.PeriodicPayment, users should not
|
|
||||||
* set the tfLoanOverpayment flag.
|
|
||||||
*
|
|
||||||
* Even though they're independent, loanMaximumPaymentsPerTransaction should be
|
|
||||||
* a multiple of loanPaymentsPerFeeIncrement.
|
|
||||||
*
|
|
||||||
* This number was chosen arbitrarily, but should not be changed once released
|
|
||||||
* without an amendment
|
|
||||||
*/
|
|
||||||
static constexpr int loanMaximumPaymentsPerTransaction = 100;
|
|
||||||
} // namespace Lending
|
|
||||||
|
|
||||||
/** The maximum length of a URI inside an NFT */
|
/** The maximum length of a URI inside an NFT */
|
||||||
std::size_t constexpr maxTokenURILength = 256;
|
std::size_t constexpr maxTokenURILength = 256;
|
||||||
|
|
||||||
@@ -252,7 +115,6 @@ std::size_t constexpr maxMPTokenMetadataLength = 1024;
|
|||||||
|
|
||||||
/** The maximum amount of MPTokenIssuance */
|
/** The maximum amount of MPTokenIssuance */
|
||||||
std::uint64_t constexpr maxMPTokenAmount = 0x7FFF'FFFF'FFFF'FFFFull;
|
std::uint64_t constexpr maxMPTokenAmount = 0x7FFF'FFFF'FFFF'FFFFull;
|
||||||
static_assert(Number::maxRep >= maxMPTokenAmount);
|
|
||||||
|
|
||||||
/** The maximum length of Data payload */
|
/** The maximum length of Data payload */
|
||||||
std::size_t constexpr maxDataPayloadLength = 256;
|
std::size_t constexpr maxDataPayloadLength = 256;
|
||||||
|
|||||||
@@ -28,22 +28,6 @@
|
|||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
/** Check whether a feature is enabled in the current ledger rules
|
|
||||||
*
|
|
||||||
* @param feature The feature to be tested.
|
|
||||||
* @param resultIfNoRules What to return if called from outside a Transactor
|
|
||||||
* context.
|
|
||||||
*/
|
|
||||||
bool
|
|
||||||
isFeatureEnabled(uint256 const& feature, bool resultIfNoRules);
|
|
||||||
|
|
||||||
/** Check whether a feature is enabled in the current ledger rules
|
|
||||||
*
|
|
||||||
* @param feature The feature to be tested.
|
|
||||||
*
|
|
||||||
* Returns false if no global Rules object is available. i.e. Outside of
|
|
||||||
* a Transactor context
|
|
||||||
*/
|
|
||||||
bool
|
bool
|
||||||
isFeatureEnabled(uint256 const& feature);
|
isFeatureEnabled(uint256 const& feature);
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
|
|
||||||
#include <xrpl/basics/safe_cast.h>
|
#include <xrpl/basics/safe_cast.h>
|
||||||
#include <xrpl/json/json_value.h>
|
#include <xrpl/json/json_value.h>
|
||||||
#include <xrpl/protocol/Units.h>
|
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <map>
|
#include <map>
|
||||||
@@ -72,10 +71,8 @@ class STCurrency;
|
|||||||
STYPE(STI_VL, 7) \
|
STYPE(STI_VL, 7) \
|
||||||
STYPE(STI_ACCOUNT, 8) \
|
STYPE(STI_ACCOUNT, 8) \
|
||||||
STYPE(STI_NUMBER, 9) \
|
STYPE(STI_NUMBER, 9) \
|
||||||
STYPE(STI_INT32, 10) \
|
|
||||||
STYPE(STI_INT64, 11) \
|
|
||||||
\
|
\
|
||||||
/* 12-13 are reserved */ \
|
/* 10-13 are reserved */ \
|
||||||
STYPE(STI_OBJECT, 14) \
|
STYPE(STI_OBJECT, 14) \
|
||||||
STYPE(STI_ARRAY, 15) \
|
STYPE(STI_ARRAY, 15) \
|
||||||
\
|
\
|
||||||
@@ -139,8 +136,8 @@ field_code(int id, int index)
|
|||||||
SFields are created at compile time.
|
SFields are created at compile time.
|
||||||
|
|
||||||
Each SField, once constructed, lives until program termination, and there
|
Each SField, once constructed, lives until program termination, and there
|
||||||
is only one instance per fieldType/fieldValue pair which serves the
|
is only one instance per fieldType/fieldValue pair which serves the entire
|
||||||
entire application.
|
application.
|
||||||
*/
|
*/
|
||||||
class SField
|
class SField
|
||||||
{
|
{
|
||||||
@@ -151,13 +148,8 @@ public:
|
|||||||
sMD_ChangeNew = 0x02, // new value when it changes
|
sMD_ChangeNew = 0x02, // new value when it changes
|
||||||
sMD_DeleteFinal = 0x04, // final value when it is deleted
|
sMD_DeleteFinal = 0x04, // final value when it is deleted
|
||||||
sMD_Create = 0x08, // value when it's created
|
sMD_Create = 0x08, // value when it's created
|
||||||
sMD_Always = 0x10, // value when node containing it is affected at all
|
sMD_Always = 0x10, // value when node containing it is affected at all
|
||||||
sMD_BaseTen = 0x20, // value is treated as base 10, overriding behavior
|
sMD_BaseTen = 0x20,
|
||||||
sMD_PseudoAccount = 0x40, // if this field is set in an ACCOUNT_ROOT
|
|
||||||
// _only_, then it is a pseudo-account
|
|
||||||
sMD_NeedsAsset = 0x80, // This field needs to be associated with an
|
|
||||||
// asset before it is serialized as a ledger
|
|
||||||
// object. Intended for STNumber.
|
|
||||||
sMD_Default =
|
sMD_Default =
|
||||||
sMD_ChangeOrig | sMD_ChangeNew | sMD_DeleteFinal | sMD_Create
|
sMD_ChangeOrig | sMD_ChangeNew | sMD_DeleteFinal | sMD_Create
|
||||||
};
|
};
|
||||||
@@ -192,7 +184,7 @@ public:
|
|||||||
char const* fn,
|
char const* fn,
|
||||||
int meta = sMD_Default,
|
int meta = sMD_Default,
|
||||||
IsSigning signing = IsSigning::yes);
|
IsSigning signing = IsSigning::yes);
|
||||||
explicit SField(private_access_tag_t, int fc, char const* fn);
|
explicit SField(private_access_tag_t, int fc);
|
||||||
|
|
||||||
static SField const&
|
static SField const&
|
||||||
getField(int fieldCode);
|
getField(int fieldCode);
|
||||||
@@ -305,7 +297,7 @@ public:
|
|||||||
static int
|
static int
|
||||||
compare(SField const& f1, SField const& f2);
|
compare(SField const& f1, SField const& f2);
|
||||||
|
|
||||||
static std::unordered_map<int, SField const*> const&
|
static std::map<int, SField const*> const&
|
||||||
getKnownCodeToField()
|
getKnownCodeToField()
|
||||||
{
|
{
|
||||||
return knownCodeToField;
|
return knownCodeToField;
|
||||||
@@ -313,8 +305,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
static int num;
|
static int num;
|
||||||
static std::unordered_map<int, SField const*> knownCodeToField;
|
static std::map<int, SField const*> knownCodeToField;
|
||||||
static std::unordered_map<std::string, SField const*> knownNameToField;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A field with a type known at compile time. */
|
/** A field with a type known at compile time. */
|
||||||
@@ -361,9 +352,6 @@ using SF_UINT256 = TypedField<STBitString<256>>;
|
|||||||
using SF_UINT384 = TypedField<STBitString<384>>;
|
using SF_UINT384 = TypedField<STBitString<384>>;
|
||||||
using SF_UINT512 = TypedField<STBitString<512>>;
|
using SF_UINT512 = TypedField<STBitString<512>>;
|
||||||
|
|
||||||
using SF_INT32 = TypedField<STInteger<std::int32_t>>;
|
|
||||||
using SF_INT64 = TypedField<STInteger<std::int64_t>>;
|
|
||||||
|
|
||||||
using SF_ACCOUNT = TypedField<STAccount>;
|
using SF_ACCOUNT = TypedField<STAccount>;
|
||||||
using SF_AMOUNT = TypedField<STAmount>;
|
using SF_AMOUNT = TypedField<STAmount>;
|
||||||
using SF_ISSUE = TypedField<STIssue>;
|
using SF_ISSUE = TypedField<STIssue>;
|
||||||
|
|||||||
@@ -62,22 +62,20 @@ private:
|
|||||||
public:
|
public:
|
||||||
using value_type = STAmount;
|
using value_type = STAmount;
|
||||||
|
|
||||||
static constexpr int cMinOffset = -96;
|
static int const cMinOffset = -96;
|
||||||
static constexpr int cMaxOffset = 80;
|
static int const cMaxOffset = 80;
|
||||||
|
|
||||||
// Maximum native value supported by the code
|
// Maximum native value supported by the code
|
||||||
constexpr static std::uint64_t cMinValue = 1'000'000'000'000'000ull;
|
static std::uint64_t const cMinValue = 1000000000000000ull;
|
||||||
static_assert(isPowerOfTen(cMinValue));
|
static std::uint64_t const cMaxValue = 9999999999999999ull;
|
||||||
constexpr static std::uint64_t cMaxValue = cMinValue * 10 - 1;
|
static std::uint64_t const cMaxNative = 9000000000000000000ull;
|
||||||
static_assert(cMaxValue == 9'999'999'999'999'999ull);
|
|
||||||
constexpr static std::uint64_t cMaxNative = 9'000'000'000'000'000'000ull;
|
|
||||||
|
|
||||||
// Max native value on network.
|
// Max native value on network.
|
||||||
constexpr static std::uint64_t cMaxNativeN = 100'000'000'000'000'000ull;
|
static std::uint64_t const cMaxNativeN = 100000000000000000ull;
|
||||||
constexpr static std::uint64_t cIssuedCurrency = 0x8'000'000'000'000'000ull;
|
static std::uint64_t const cIssuedCurrency = 0x8000000000000000ull;
|
||||||
constexpr static std::uint64_t cPositive = 0x4'000'000'000'000'000ull;
|
static std::uint64_t const cPositive = 0x4000000000000000ull;
|
||||||
constexpr static std::uint64_t cMPToken = 0x2'000'000'000'000'000ull;
|
static std::uint64_t const cMPToken = 0x2000000000000000ull;
|
||||||
constexpr static std::uint64_t cValueMask = ~(cPositive | cMPToken);
|
static std::uint64_t const cValueMask = ~(cPositive | cMPToken);
|
||||||
|
|
||||||
static std::uint64_t const uRateOne;
|
static std::uint64_t const uRateOne;
|
||||||
|
|
||||||
@@ -157,7 +155,7 @@ public:
|
|||||||
|
|
||||||
template <AssetType A>
|
template <AssetType A>
|
||||||
STAmount(A const& asset, Number const& number)
|
STAmount(A const& asset, Number const& number)
|
||||||
: STAmount(fromNumber(asset, number))
|
: STAmount(asset, number.mantissa(), number.exponent())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,9 +174,6 @@ public:
|
|||||||
int
|
int
|
||||||
exponent() const noexcept;
|
exponent() const noexcept;
|
||||||
|
|
||||||
bool
|
|
||||||
integral() const noexcept;
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
native() const noexcept;
|
native() const noexcept;
|
||||||
|
|
||||||
@@ -301,10 +296,6 @@ public:
|
|||||||
mpt() const;
|
mpt() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <AssetType A>
|
|
||||||
static STAmount
|
|
||||||
fromNumber(A const& asset, Number const& number);
|
|
||||||
|
|
||||||
static std::unique_ptr<STAmount>
|
static std::unique_ptr<STAmount>
|
||||||
construct(SerialIter&, SField const& name);
|
construct(SerialIter&, SField const& name);
|
||||||
|
|
||||||
@@ -368,19 +359,10 @@ STAmount::STAmount(
|
|||||||
, mIsNegative(negative)
|
, mIsNegative(negative)
|
||||||
{
|
{
|
||||||
// mValue is uint64, but needs to fit in the range of int64
|
// mValue is uint64, but needs to fit in the range of int64
|
||||||
if (Number::getMantissaScale() == MantissaRange::small)
|
XRPL_ASSERT(
|
||||||
{
|
mValue <= std::numeric_limits<std::int64_t>::max(),
|
||||||
XRPL_ASSERT(
|
"ripple::STAmount::STAmount(SField, A, std::uint64_t, int, bool) : "
|
||||||
mValue <= std::numeric_limits<std::int64_t>::max(),
|
"maximum mantissa input");
|
||||||
"ripple::STAmount::STAmount(SField, A, std::uint64_t, int, bool) : "
|
|
||||||
"maximum mantissa input");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (integral() && mValue > std::numeric_limits<std::int64_t>::max())
|
|
||||||
throw std::overflow_error(
|
|
||||||
"STAmount mantissa is too large " + std::to_string(mantissa));
|
|
||||||
}
|
|
||||||
canonicalize();
|
canonicalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -472,12 +454,6 @@ STAmount::exponent() const noexcept
|
|||||||
return mOffset;
|
return mOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
|
||||||
STAmount::integral() const noexcept
|
|
||||||
{
|
|
||||||
return mAsset.integral();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
STAmount::native() const noexcept
|
STAmount::native() const noexcept
|
||||||
{
|
{
|
||||||
@@ -574,23 +550,14 @@ STAmount::operator=(XRPAmount const& amount)
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <AssetType A>
|
inline STAmount&
|
||||||
inline STAmount
|
STAmount::operator=(Number const& number)
|
||||||
STAmount::fromNumber(A const& a, Number const& number)
|
|
||||||
{
|
{
|
||||||
bool const negative = number.mantissa() < 0;
|
mIsNegative = number.mantissa() < 0;
|
||||||
Number const working{negative ? -number : number};
|
mValue = mIsNegative ? -number.mantissa() : number.mantissa();
|
||||||
Asset asset{a};
|
mOffset = number.exponent();
|
||||||
if (asset.integral())
|
canonicalize();
|
||||||
{
|
return *this;
|
||||||
std::uint64_t const intValue = static_cast<std::int64_t>(working);
|
|
||||||
return STAmount{asset, intValue, 0, negative};
|
|
||||||
}
|
|
||||||
|
|
||||||
auto const [mantissa, exponent] =
|
|
||||||
working.normalizeToRange(cMinValue, cMaxValue);
|
|
||||||
|
|
||||||
return STAmount{asset, mantissa, exponent, negative};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
@@ -605,7 +572,7 @@ STAmount::clear()
|
|||||||
{
|
{
|
||||||
// The -100 is used to allow 0 to sort less than a small positive values
|
// The -100 is used to allow 0 to sort less than a small positive values
|
||||||
// which have a negative exponent.
|
// which have a negative exponent.
|
||||||
mOffset = integral() ? 0 : -100;
|
mOffset = native() ? 0 : -100;
|
||||||
mValue = 0;
|
mValue = 0;
|
||||||
mIsNegative = false;
|
mIsNegative = false;
|
||||||
}
|
}
|
||||||
@@ -728,68 +695,6 @@ divRoundStrict(
|
|||||||
std::uint64_t
|
std::uint64_t
|
||||||
getRate(STAmount const& offerOut, STAmount const& offerIn);
|
getRate(STAmount const& offerOut, STAmount const& offerIn);
|
||||||
|
|
||||||
/** Round an arbitrary precision Amount to the precision of an STAmount that has
|
|
||||||
* a given exponent.
|
|
||||||
*
|
|
||||||
* This is used to ensure that calculations involving IOU amounts do not collect
|
|
||||||
* dust beyond the precision of the reference value.
|
|
||||||
*
|
|
||||||
* @param value The value to be rounded
|
|
||||||
* @param scale An exponent value to establish the precision limit of
|
|
||||||
* `value`. Should be larger than `value.exponent()`.
|
|
||||||
* @param rounding Optional Number rounding mode
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
[[nodiscard]] STAmount
|
|
||||||
roundToScale(
|
|
||||||
STAmount const& value,
|
|
||||||
std::int32_t scale,
|
|
||||||
Number::rounding_mode rounding = Number::getround());
|
|
||||||
|
|
||||||
/** Round an arbitrary precision Number IN PLACE to the precision of a given
|
|
||||||
* Asset.
|
|
||||||
*
|
|
||||||
* This is used to ensure that calculations do not collect dust for IOUs, or
|
|
||||||
* fractional amounts for the integral types XRP and MPT.
|
|
||||||
*
|
|
||||||
* @param asset The relevant asset
|
|
||||||
* @param value The lvalue to be rounded
|
|
||||||
*/
|
|
||||||
template <AssetType A>
|
|
||||||
void
|
|
||||||
roundToAsset(A const& asset, Number& value)
|
|
||||||
{
|
|
||||||
value = STAmount{asset, value};
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Round an arbitrary precision Number to the precision of a given Asset.
|
|
||||||
*
|
|
||||||
* This is used to ensure that calculations do not collect dust beyond specified
|
|
||||||
* scale for IOUs, or fractional amounts for the integral types XRP and MPT.
|
|
||||||
*
|
|
||||||
* @param asset The relevant asset
|
|
||||||
* @param value The value to be rounded
|
|
||||||
* @param scale Only relevant to IOU assets. An exponent value to establish the
|
|
||||||
* precision limit of `value`. Should be larger than `value.exponent()`.
|
|
||||||
* @param rounding Optional Number rounding mode
|
|
||||||
*/
|
|
||||||
template <AssetType A>
|
|
||||||
[[nodiscard]] Number
|
|
||||||
roundToAsset(
|
|
||||||
A const& asset,
|
|
||||||
Number const& value,
|
|
||||||
std::int32_t scale,
|
|
||||||
Number::rounding_mode rounding = Number::getround())
|
|
||||||
{
|
|
||||||
NumberRoundModeGuard mg(rounding);
|
|
||||||
STAmount const ret{asset, value};
|
|
||||||
if (ret.integral())
|
|
||||||
return ret;
|
|
||||||
// Note that the ctor will round integral types (XRP, MPT) via canonicalize,
|
|
||||||
// so no extra work is needed for those.
|
|
||||||
return roundToScale(ret, scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
@@ -804,22 +709,6 @@ canAdd(STAmount const& amt1, STAmount const& amt2);
|
|||||||
bool
|
bool
|
||||||
canSubtract(STAmount const& amt1, STAmount const& amt2);
|
canSubtract(STAmount const& amt1, STAmount const& amt2);
|
||||||
|
|
||||||
/** Get the scale of a Number for a given asset.
|
|
||||||
*
|
|
||||||
* "scale" is similar to "exponent", but from the perspective of STAmount, which
|
|
||||||
* has different rules and mantissa ranges for determining the exponent than
|
|
||||||
* Number.
|
|
||||||
*
|
|
||||||
* @param number The Number to get the scale of.
|
|
||||||
* @param asset The asset to use for determining the scale.
|
|
||||||
* @return The scale of this Number for the given asset.
|
|
||||||
*/
|
|
||||||
inline int
|
|
||||||
scale(Number const& number, Asset const& asset)
|
|
||||||
{
|
|
||||||
return STAmount{asset, number}.exponent();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Since `canonicalize` does not have access to a ledger, this is needed to put
|
// Since `canonicalize` does not have access to a ledger, this is needed to put
|
||||||
// the low-level routine stAmountCanonicalize on an amendment switch. Only
|
// the low-level routine stAmountCanonicalize on an amendment switch. Only
|
||||||
// transactions need to use this switchover. Outside of a transaction it's safe
|
// transactions need to use this switchover. Outside of a transaction it's safe
|
||||||
|
|||||||
@@ -81,8 +81,6 @@ using STUInt16 = STInteger<std::uint16_t>;
|
|||||||
using STUInt32 = STInteger<std::uint32_t>;
|
using STUInt32 = STInteger<std::uint32_t>;
|
||||||
using STUInt64 = STInteger<std::uint64_t>;
|
using STUInt64 = STInteger<std::uint64_t>;
|
||||||
|
|
||||||
using STInt32 = STInteger<std::int32_t>;
|
|
||||||
|
|
||||||
template <typename Integer>
|
template <typename Integer>
|
||||||
inline STInteger<Integer>::STInteger(Integer v) : value_(v)
|
inline STInteger<Integer>::STInteger(Integer v) : value_(v)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -26,9 +26,7 @@
|
|||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
class Rules;
|
class Rules;
|
||||||
namespace test {
|
|
||||||
class Invariants_test;
|
class Invariants_test;
|
||||||
}
|
|
||||||
|
|
||||||
class STLedgerEntry final : public STObject, public CountedObject<STLedgerEntry>
|
class STLedgerEntry final : public STObject, public CountedObject<STLedgerEntry>
|
||||||
{
|
{
|
||||||
@@ -38,8 +36,6 @@ class STLedgerEntry final : public STObject, public CountedObject<STLedgerEntry>
|
|||||||
public:
|
public:
|
||||||
using pointer = std::shared_ptr<STLedgerEntry>;
|
using pointer = std::shared_ptr<STLedgerEntry>;
|
||||||
using ref = std::shared_ptr<STLedgerEntry> const&;
|
using ref = std::shared_ptr<STLedgerEntry> const&;
|
||||||
using const_pointer = std::shared_ptr<STLedgerEntry const>;
|
|
||||||
using const_ref = std::shared_ptr<STLedgerEntry const> const&;
|
|
||||||
|
|
||||||
/** Create an empty object with the given key and type. */
|
/** Create an empty object with the given key and type. */
|
||||||
explicit STLedgerEntry(Keylet const& k);
|
explicit STLedgerEntry(Keylet const& k);
|
||||||
@@ -58,7 +54,7 @@ public:
|
|||||||
getText() const override;
|
getText() const override;
|
||||||
|
|
||||||
Json::Value
|
Json::Value
|
||||||
getJson(JsonOptions options = JsonOptions::none) const override;
|
getJson(JsonOptions options) const override;
|
||||||
|
|
||||||
/** Returns the 'key' (or 'index') of this item.
|
/** Returns the 'key' (or 'index') of this item.
|
||||||
The key identifies this entry's position in
|
The key identifies this entry's position in
|
||||||
@@ -88,8 +84,7 @@ private:
|
|||||||
void
|
void
|
||||||
setSLEType();
|
setSLEType();
|
||||||
|
|
||||||
friend test::Invariants_test; // this test wants access to the private
|
friend Invariants_test; // this test wants access to the private type_
|
||||||
// type_
|
|
||||||
|
|
||||||
STBase*
|
STBase*
|
||||||
copy(std::size_t n, void* buf) const override;
|
copy(std::size_t n, void* buf) const override;
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
#include <xrpl/basics/CountedObject.h>
|
#include <xrpl/basics/CountedObject.h>
|
||||||
#include <xrpl/basics/Number.h>
|
#include <xrpl/basics/Number.h>
|
||||||
#include <xrpl/protocol/STBase.h>
|
#include <xrpl/protocol/STBase.h>
|
||||||
#include <xrpl/protocol/STTakesAsset.h>
|
|
||||||
|
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
|
||||||
@@ -39,19 +38,8 @@ namespace ripple {
|
|||||||
* it can represent a value of any token type (XRP, IOU, or MPT)
|
* it can represent a value of any token type (XRP, IOU, or MPT)
|
||||||
* without paying the storage cost of duplicating asset information
|
* without paying the storage cost of duplicating asset information
|
||||||
* that may be deduced from the context.
|
* that may be deduced from the context.
|
||||||
*
|
|
||||||
* STNumber derives from STTakesAsset, so that it can be associated with the
|
|
||||||
* related Asset during transaction processing. Which asset is relevant depends
|
|
||||||
* on the object and transaction. As of this writing, only Vault, LoanBroker,
|
|
||||||
* and Loan objects use STNumber fields. All of those fields represent amounts
|
|
||||||
* of the Vault's Asset, so they should be associated with the Vault's Asset.
|
|
||||||
*
|
|
||||||
* e.g.
|
|
||||||
* associateAsset(*loanSle, asset);
|
|
||||||
* associateAsset(*brokerSle, asset);
|
|
||||||
* associateAsset(*vaultSle, asset);
|
|
||||||
*/
|
*/
|
||||||
class STNumber : public STTakesAsset, public CountedObject<STNumber>
|
class STNumber : public STBase, public CountedObject<STNumber>
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
Number value_;
|
Number value_;
|
||||||
@@ -87,9 +75,6 @@ public:
|
|||||||
bool
|
bool
|
||||||
isDefault() const override;
|
isDefault() const override;
|
||||||
|
|
||||||
void
|
|
||||||
associateAsset(Asset const& a) override;
|
|
||||||
|
|
||||||
operator Number() const
|
operator Number() const
|
||||||
{
|
{
|
||||||
return value_;
|
return value_;
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
#include <xrpl/basics/chrono.h>
|
#include <xrpl/basics/chrono.h>
|
||||||
#include <xrpl/basics/contract.h>
|
#include <xrpl/basics/contract.h>
|
||||||
#include <xrpl/beast/utility/instrumentation.h>
|
#include <xrpl/beast/utility/instrumentation.h>
|
||||||
|
#include <xrpl/protocol/FeeUnits.h>
|
||||||
#include <xrpl/protocol/HashPrefix.h>
|
#include <xrpl/protocol/HashPrefix.h>
|
||||||
#include <xrpl/protocol/SOTemplate.h>
|
#include <xrpl/protocol/SOTemplate.h>
|
||||||
#include <xrpl/protocol/STAmount.h>
|
#include <xrpl/protocol/STAmount.h>
|
||||||
@@ -33,7 +34,6 @@
|
|||||||
#include <xrpl/protocol/STIssue.h>
|
#include <xrpl/protocol/STIssue.h>
|
||||||
#include <xrpl/protocol/STPathSet.h>
|
#include <xrpl/protocol/STPathSet.h>
|
||||||
#include <xrpl/protocol/STVector256.h>
|
#include <xrpl/protocol/STVector256.h>
|
||||||
#include <xrpl/protocol/Units.h>
|
|
||||||
#include <xrpl/protocol/detail/STVar.h>
|
#include <xrpl/protocol/detail/STVar.h>
|
||||||
|
|
||||||
#include <boost/iterator/transform_iterator.hpp>
|
#include <boost/iterator/transform_iterator.hpp>
|
||||||
@@ -231,8 +231,6 @@ public:
|
|||||||
getFieldH192(SField const& field) const;
|
getFieldH192(SField const& field) const;
|
||||||
uint256
|
uint256
|
||||||
getFieldH256(SField const& field) const;
|
getFieldH256(SField const& field) const;
|
||||||
std::int32_t
|
|
||||||
getFieldI32(SField const& field) const;
|
|
||||||
AccountID
|
AccountID
|
||||||
getAccountID(SField const& field) const;
|
getAccountID(SField const& field) const;
|
||||||
|
|
||||||
@@ -244,9 +242,6 @@ public:
|
|||||||
getFieldPathSet(SField const& field) const;
|
getFieldPathSet(SField const& field) const;
|
||||||
STVector256 const&
|
STVector256 const&
|
||||||
getFieldV256(SField const& field) const;
|
getFieldV256(SField const& field) const;
|
||||||
// If not found, returns an object constructed with the given field
|
|
||||||
STObject
|
|
||||||
getFieldObject(SField const& field) const;
|
|
||||||
STArray const&
|
STArray const&
|
||||||
getFieldArray(SField const& field) const;
|
getFieldArray(SField const& field) const;
|
||||||
STCurrency const&
|
STCurrency const&
|
||||||
@@ -370,8 +365,6 @@ public:
|
|||||||
void
|
void
|
||||||
setFieldH256(SField const& field, uint256 const&);
|
setFieldH256(SField const& field, uint256 const&);
|
||||||
void
|
void
|
||||||
setFieldI32(SField const& field, std::int32_t);
|
|
||||||
void
|
|
||||||
setFieldVL(SField const& field, Blob const&);
|
setFieldVL(SField const& field, Blob const&);
|
||||||
void
|
void
|
||||||
setFieldVL(SField const& field, Slice const&);
|
setFieldVL(SField const& field, Slice const&);
|
||||||
@@ -393,8 +386,6 @@ public:
|
|||||||
setFieldV256(SField const& field, STVector256 const& v);
|
setFieldV256(SField const& field, STVector256 const& v);
|
||||||
void
|
void
|
||||||
setFieldArray(SField const& field, STArray const& v);
|
setFieldArray(SField const& field, STArray const& v);
|
||||||
void
|
|
||||||
setFieldObject(SField const& field, STObject const& v);
|
|
||||||
|
|
||||||
template <class Tag>
|
template <class Tag>
|
||||||
void
|
void
|
||||||
@@ -416,9 +407,6 @@ public:
|
|||||||
void
|
void
|
||||||
delField(int index);
|
delField(int index);
|
||||||
|
|
||||||
SOEStyle
|
|
||||||
getStyle(SField const& field) const;
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
hasMatchingEntry(STBase const&);
|
hasMatchingEntry(STBase const&);
|
||||||
|
|
||||||
@@ -504,8 +492,6 @@ public:
|
|||||||
value_type
|
value_type
|
||||||
operator*() const;
|
operator*() const;
|
||||||
|
|
||||||
/// Do not use operator->() unless the field is required, or you've checked
|
|
||||||
/// that it's set.
|
|
||||||
T const*
|
T const*
|
||||||
operator->() const;
|
operator->() const;
|
||||||
|
|
||||||
@@ -529,26 +515,7 @@ protected:
|
|||||||
// Constraint += and -= ValueProxy operators
|
// Constraint += and -= ValueProxy operators
|
||||||
// to value types that support arithmetic operations
|
// to value types that support arithmetic operations
|
||||||
template <typename U>
|
template <typename U>
|
||||||
concept IsArithmeticNumber = std::is_arithmetic_v<U> ||
|
concept IsArithmetic = std::is_arithmetic_v<U> || std::is_same_v<U, STAmount>;
|
||||||
std::is_same_v<U, Number> || std::is_same_v<U, STAmount>;
|
|
||||||
template <
|
|
||||||
typename U,
|
|
||||||
typename Value = typename U::value_type,
|
|
||||||
typename Unit = typename U::unit_type>
|
|
||||||
concept IsArithmeticValueUnit =
|
|
||||||
std::is_same_v<U, unit::ValueUnit<Unit, Value>> &&
|
|
||||||
IsArithmeticNumber<Value> && std::is_class_v<Unit>;
|
|
||||||
template <typename U, typename Value = typename U::value_type>
|
|
||||||
concept IsArithmeticST = !IsArithmeticValueUnit<U> && IsArithmeticNumber<Value>;
|
|
||||||
template <typename U>
|
|
||||||
concept IsArithmetic =
|
|
||||||
IsArithmeticNumber<U> || IsArithmeticST<U> || IsArithmeticValueUnit<U>;
|
|
||||||
|
|
||||||
template <class T, class U>
|
|
||||||
concept Addable = requires(T t, U u) { t = t + u; };
|
|
||||||
template <typename T, typename U>
|
|
||||||
concept IsArithmeticCompatible =
|
|
||||||
IsArithmetic<typename T::value_type> && Addable<typename T::value_type, U>;
|
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
class STObject::ValueProxy : public Proxy<T>
|
class STObject::ValueProxy : public Proxy<T>
|
||||||
@@ -568,12 +535,10 @@ public:
|
|||||||
// Convenience operators for value types supporting
|
// Convenience operators for value types supporting
|
||||||
// arithmetic operations
|
// arithmetic operations
|
||||||
template <IsArithmetic U>
|
template <IsArithmetic U>
|
||||||
requires IsArithmeticCompatible<T, U>
|
|
||||||
ValueProxy&
|
ValueProxy&
|
||||||
operator+=(U const& u);
|
operator+=(U const& u);
|
||||||
|
|
||||||
template <IsArithmetic U>
|
template <IsArithmetic U>
|
||||||
requires IsArithmeticCompatible<T, U>
|
|
||||||
ValueProxy&
|
ValueProxy&
|
||||||
operator-=(U const& u);
|
operator-=(U const& u);
|
||||||
|
|
||||||
@@ -763,8 +728,6 @@ STObject::Proxy<T>::operator*() const -> value_type
|
|||||||
return this->value();
|
return this->value();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Do not use operator->() unless the field is required, or you've checked that
|
|
||||||
/// it's set.
|
|
||||||
template <class T>
|
template <class T>
|
||||||
T const*
|
T const*
|
||||||
STObject::Proxy<T>::operator->() const
|
STObject::Proxy<T>::operator->() const
|
||||||
@@ -811,7 +774,6 @@ STObject::ValueProxy<T>::operator=(U&& u)
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
template <IsArithmetic U>
|
template <IsArithmetic U>
|
||||||
requires IsArithmeticCompatible<T, U>
|
|
||||||
STObject::ValueProxy<T>&
|
STObject::ValueProxy<T>&
|
||||||
STObject::ValueProxy<T>::operator+=(U const& u)
|
STObject::ValueProxy<T>::operator+=(U const& u)
|
||||||
{
|
{
|
||||||
@@ -821,7 +783,6 @@ STObject::ValueProxy<T>::operator+=(U const& u)
|
|||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
template <IsArithmetic U>
|
template <IsArithmetic U>
|
||||||
requires IsArithmeticCompatible<T, U>
|
|
||||||
STObject::ValueProxy<T>&
|
STObject::ValueProxy<T>&
|
||||||
STObject::ValueProxy<T>::operator-=(U const& u)
|
STObject::ValueProxy<T>::operator-=(U const& u)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -26,13 +26,6 @@
|
|||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
/** Maximum JSON object nesting depth permitted during parsing. */
|
|
||||||
inline constexpr std::size_t maxSTParsedJSONDepth = 64;
|
|
||||||
|
|
||||||
/** Maximum number of elements permitted in any JSON array field during parsing.
|
|
||||||
Requests exceeding this limit are rejected with an invalidParams error. */
|
|
||||||
inline constexpr std::size_t maxSTParsedJSONArraySize = 512;
|
|
||||||
|
|
||||||
/** Holds the serialized result of parsing an input JSON object.
|
/** Holds the serialized result of parsing an input JSON object.
|
||||||
This does validation and checking on the provided JSON.
|
This does validation and checking on the provided JSON.
|
||||||
*/
|
*/
|
||||||
@@ -61,6 +54,34 @@ public:
|
|||||||
Json::Value error;
|
Json::Value error;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Holds the serialized result of parsing an input JSON array.
|
||||||
|
This does validation and checking on the provided JSON.
|
||||||
|
*/
|
||||||
|
class STParsedJSONArray
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/** Parses and creates an STParsedJSON array.
|
||||||
|
The result of the parsing is stored in array and error.
|
||||||
|
Exceptions:
|
||||||
|
Does not throw.
|
||||||
|
@param name The name of the JSON field, used in diagnostics.
|
||||||
|
@param json The JSON-RPC to parse.
|
||||||
|
*/
|
||||||
|
STParsedJSONArray(std::string const& name, Json::Value const& json);
|
||||||
|
|
||||||
|
STParsedJSONArray() = delete;
|
||||||
|
STParsedJSONArray(STParsedJSONArray const&) = delete;
|
||||||
|
STParsedJSONArray&
|
||||||
|
operator=(STParsedJSONArray const&) = delete;
|
||||||
|
~STParsedJSONArray() = default;
|
||||||
|
|
||||||
|
/** The STArray if the parse was successful. */
|
||||||
|
std::optional<STArray> array;
|
||||||
|
|
||||||
|
/** On failure, an appropriate set of error values. */
|
||||||
|
Json::Value error;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace ripple
|
} // namespace ripple
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,63 +0,0 @@
|
|||||||
#ifndef XRPL_PROTOCOL_STTAKESASSET_H_INCLUDED
|
|
||||||
#define XRPL_PROTOCOL_STTAKESASSET_H_INCLUDED
|
|
||||||
|
|
||||||
#include <xrpl/protocol/Asset.h>
|
|
||||||
#include <xrpl/protocol/STBase.h>
|
|
||||||
|
|
||||||
namespace ripple {
|
|
||||||
|
|
||||||
/** Intermediate class for any STBase-derived class to store an Asset.
|
|
||||||
*
|
|
||||||
* In the class definition, this class should be specified as a base class
|
|
||||||
* _instead_ of STBase.
|
|
||||||
*
|
|
||||||
* Specifically, the Asset is only stored and used at runtime. It should not be
|
|
||||||
* serialized to the ledger.
|
|
||||||
*
|
|
||||||
* The derived class decides what to do with the Asset, and when. It will not
|
|
||||||
* necessarily be set at any given time. As of this writing, only STNumber uses
|
|
||||||
* it to round the stored Number to the Asset's precision both when associated,
|
|
||||||
* and when serializing the Number.
|
|
||||||
*/
|
|
||||||
class STTakesAsset : public STBase
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
std::optional<Asset> asset_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
using STBase::STBase;
|
|
||||||
using STBase::operator=;
|
|
||||||
|
|
||||||
virtual void
|
|
||||||
associateAsset(Asset const& a);
|
|
||||||
};
|
|
||||||
|
|
||||||
inline void
|
|
||||||
STTakesAsset::associateAsset(Asset const& a)
|
|
||||||
{
|
|
||||||
asset_.emplace(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
class STLedgerEntry;
|
|
||||||
|
|
||||||
/** Associate an Asset with all sMD_NeedsAsset fields in a ledger entry.
|
|
||||||
*
|
|
||||||
* This function iterates over all fields in the given ledger entry. For each
|
|
||||||
* field that is set and has the SField::sMD_NeedsAsset metadata flag, it calls
|
|
||||||
* `associateAsset` on that field with the given Asset. Such field must be
|
|
||||||
* derived from STTakesAsset - if it is not, the conversion will throw.
|
|
||||||
*
|
|
||||||
* Typically, associateAsset should be called near the end of doApply() of any
|
|
||||||
* Transactor classes on the SLEs of any new or modified ledger entries
|
|
||||||
* containing STNumber fields, after doing all of the modifications t the SLEs.
|
|
||||||
*
|
|
||||||
* @param sle The ledger entry whose fields will be updated.
|
|
||||||
* @param asset The Asset to associate with the relevant fields.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
associateAsset(STLedgerEntry& sle, Asset const& asset);
|
|
||||||
|
|
||||||
} // namespace ripple
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -87,14 +87,8 @@ public:
|
|||||||
getFullText() const override;
|
getFullText() const override;
|
||||||
|
|
||||||
// Outer transaction functions / signature functions.
|
// Outer transaction functions / signature functions.
|
||||||
static Blob
|
|
||||||
getSignature(STObject const& sigObject);
|
|
||||||
|
|
||||||
Blob
|
Blob
|
||||||
getSignature() const
|
getSignature() const;
|
||||||
{
|
|
||||||
return getSignature(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint256
|
uint256
|
||||||
getSigningHash() const;
|
getSigningHash() const;
|
||||||
@@ -125,20 +119,13 @@ public:
|
|||||||
getJson(JsonOptions options, bool binary) const;
|
getJson(JsonOptions options, bool binary) const;
|
||||||
|
|
||||||
void
|
void
|
||||||
sign(
|
sign(PublicKey const& publicKey, SecretKey const& secretKey);
|
||||||
PublicKey const& publicKey,
|
|
||||||
SecretKey const& secretKey,
|
|
||||||
std::optional<std::reference_wrapper<SField const>> signatureTarget =
|
|
||||||
{});
|
|
||||||
|
|
||||||
enum class RequireFullyCanonicalSig : bool { no, yes };
|
|
||||||
|
|
||||||
/** Check the signature.
|
/** Check the signature.
|
||||||
@param requireCanonicalSig If `true`, check that the signature is fully
|
|
||||||
canonical. If `false`, only check that the signature is valid.
|
|
||||||
@param rules The current ledger rules.
|
|
||||||
@return `true` if valid signature. If invalid, the error message string.
|
@return `true` if valid signature. If invalid, the error message string.
|
||||||
*/
|
*/
|
||||||
|
enum class RequireFullyCanonicalSig : bool { no, yes };
|
||||||
|
|
||||||
Expected<void, std::string>
|
Expected<void, std::string>
|
||||||
checkSign(RequireFullyCanonicalSig requireCanonicalSig, Rules const& rules)
|
checkSign(RequireFullyCanonicalSig requireCanonicalSig, Rules const& rules)
|
||||||
const;
|
const;
|
||||||
@@ -163,34 +150,17 @@ public:
|
|||||||
char status,
|
char status,
|
||||||
std::string const& escapedMetaData) const;
|
std::string const& escapedMetaData) const;
|
||||||
|
|
||||||
std::vector<uint256> const&
|
std::vector<uint256>
|
||||||
getBatchTransactionIDs() const;
|
getBatchTransactionIDs() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** Check the signature.
|
|
||||||
@param requireCanonicalSig If `true`, check that the signature is fully
|
|
||||||
canonical. If `false`, only check that the signature is valid.
|
|
||||||
@param rules The current ledger rules.
|
|
||||||
@param sigObject Reference to object that contains the signature fields.
|
|
||||||
Will be *this more often than not.
|
|
||||||
@return `true` if valid signature. If invalid, the error message string.
|
|
||||||
*/
|
|
||||||
Expected<void, std::string>
|
Expected<void, std::string>
|
||||||
checkSign(
|
checkSingleSign(RequireFullyCanonicalSig requireCanonicalSig) const;
|
||||||
RequireFullyCanonicalSig requireCanonicalSig,
|
|
||||||
Rules const& rules,
|
|
||||||
STObject const& sigObject) const;
|
|
||||||
|
|
||||||
Expected<void, std::string>
|
|
||||||
checkSingleSign(
|
|
||||||
RequireFullyCanonicalSig requireCanonicalSig,
|
|
||||||
STObject const& sigObject) const;
|
|
||||||
|
|
||||||
Expected<void, std::string>
|
Expected<void, std::string>
|
||||||
checkMultiSign(
|
checkMultiSign(
|
||||||
RequireFullyCanonicalSig requireCanonicalSig,
|
RequireFullyCanonicalSig requireCanonicalSig,
|
||||||
Rules const& rules,
|
Rules const& rules) const;
|
||||||
STObject const& sigObject) const;
|
|
||||||
|
|
||||||
Expected<void, std::string>
|
Expected<void, std::string>
|
||||||
checkBatchSingleSign(
|
checkBatchSingleSign(
|
||||||
@@ -209,7 +179,7 @@ private:
|
|||||||
move(std::size_t n, void* buf) override;
|
move(std::size_t n, void* buf) override;
|
||||||
|
|
||||||
friend class detail::STVar;
|
friend class detail::STVar;
|
||||||
mutable std::vector<uint256> batchTxnIds_;
|
mutable std::vector<uint256> batch_txn_ids_;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|||||||
@@ -22,10 +22,10 @@
|
|||||||
|
|
||||||
#include <xrpl/basics/Log.h>
|
#include <xrpl/basics/Log.h>
|
||||||
#include <xrpl/beast/utility/instrumentation.h>
|
#include <xrpl/beast/utility/instrumentation.h>
|
||||||
|
#include <xrpl/protocol/FeeUnits.h>
|
||||||
#include <xrpl/protocol/PublicKey.h>
|
#include <xrpl/protocol/PublicKey.h>
|
||||||
#include <xrpl/protocol/STObject.h>
|
#include <xrpl/protocol/STObject.h>
|
||||||
#include <xrpl/protocol/SecretKey.h>
|
#include <xrpl/protocol/SecretKey.h>
|
||||||
#include <xrpl/protocol/Units.h>
|
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|||||||
@@ -42,8 +42,6 @@ systemName()
|
|||||||
|
|
||||||
/** Number of drops in the genesis account. */
|
/** Number of drops in the genesis account. */
|
||||||
constexpr XRPAmount INITIAL_XRP{100'000'000'000 * DROPS_PER_XRP};
|
constexpr XRPAmount INITIAL_XRP{100'000'000'000 * DROPS_PER_XRP};
|
||||||
static_assert(INITIAL_XRP.drops() == 100'000'000'000'000'000);
|
|
||||||
static_assert(Number::maxRep >= INITIAL_XRP.drops());
|
|
||||||
|
|
||||||
/** Returns true if the amount does not exceed the initial XRP in existence. */
|
/** Returns true if the amount does not exceed the initial XRP in existence. */
|
||||||
inline bool
|
inline bool
|
||||||
|
|||||||
@@ -673,8 +673,7 @@ isTerRetry(TER x) noexcept
|
|||||||
inline bool
|
inline bool
|
||||||
isTesSuccess(TER x) noexcept
|
isTesSuccess(TER x) noexcept
|
||||||
{
|
{
|
||||||
// Makes use of TERSubset::operator bool()
|
return (x == tesSUCCESS);
|
||||||
return !(x);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
|
|||||||
@@ -127,8 +127,6 @@ constexpr std::uint32_t tfTrustSetPermissionMask = ~(tfUniversal | tfSetfAuth |
|
|||||||
// EnableAmendment flags:
|
// EnableAmendment flags:
|
||||||
constexpr std::uint32_t tfGotMajority = 0x00010000;
|
constexpr std::uint32_t tfGotMajority = 0x00010000;
|
||||||
constexpr std::uint32_t tfLostMajority = 0x00020000;
|
constexpr std::uint32_t tfLostMajority = 0x00020000;
|
||||||
constexpr std::uint32_t tfChangeMask =
|
|
||||||
~( tfUniversal | tfGotMajority | tfLostMajority);
|
|
||||||
|
|
||||||
// PaymentChannelClaim flags:
|
// PaymentChannelClaim flags:
|
||||||
constexpr std::uint32_t tfRenew = 0x00010000;
|
constexpr std::uint32_t tfRenew = 0x00010000;
|
||||||
@@ -143,8 +141,7 @@ constexpr std::uint32_t const tfTransferable = 0x00000008;
|
|||||||
constexpr std::uint32_t const tfMutable = 0x00000010;
|
constexpr std::uint32_t const tfMutable = 0x00000010;
|
||||||
|
|
||||||
// MPTokenIssuanceCreate flags:
|
// MPTokenIssuanceCreate flags:
|
||||||
// Note: tf/lsfMPTLocked is intentionally omitted, since this transaction
|
// NOTE - there is intentionally no flag here for lsfMPTLocked, which this transaction cannot mutate.
|
||||||
// is not allowed to modify it.
|
|
||||||
constexpr std::uint32_t const tfMPTCanLock = lsfMPTCanLock;
|
constexpr std::uint32_t const tfMPTCanLock = lsfMPTCanLock;
|
||||||
constexpr std::uint32_t const tfMPTRequireAuth = lsfMPTRequireAuth;
|
constexpr std::uint32_t const tfMPTRequireAuth = lsfMPTRequireAuth;
|
||||||
constexpr std::uint32_t const tfMPTCanEscrow = lsfMPTCanEscrow;
|
constexpr std::uint32_t const tfMPTCanEscrow = lsfMPTCanEscrow;
|
||||||
@@ -154,20 +151,6 @@ constexpr std::uint32_t const tfMPTCanClawback = lsfMPTCanClawback;
|
|||||||
constexpr std::uint32_t const tfMPTokenIssuanceCreateMask =
|
constexpr std::uint32_t const tfMPTokenIssuanceCreateMask =
|
||||||
~(tfUniversal | tfMPTCanLock | tfMPTRequireAuth | tfMPTCanEscrow | tfMPTCanTrade | tfMPTCanTransfer | tfMPTCanClawback);
|
~(tfUniversal | tfMPTCanLock | tfMPTRequireAuth | tfMPTCanEscrow | tfMPTCanTrade | tfMPTCanTransfer | tfMPTCanClawback);
|
||||||
|
|
||||||
// MPTokenIssuanceCreate MutableFlags:
|
|
||||||
// Indicating specific fields or flags may be changed after issuance.
|
|
||||||
constexpr std::uint32_t const tmfMPTCanMutateCanLock = lsmfMPTCanMutateCanLock;
|
|
||||||
constexpr std::uint32_t const tmfMPTCanMutateRequireAuth = lsmfMPTCanMutateRequireAuth;
|
|
||||||
constexpr std::uint32_t const tmfMPTCanMutateCanEscrow = lsmfMPTCanMutateCanEscrow;
|
|
||||||
constexpr std::uint32_t const tmfMPTCanMutateCanTrade = lsmfMPTCanMutateCanTrade;
|
|
||||||
constexpr std::uint32_t const tmfMPTCanMutateCanTransfer = lsmfMPTCanMutateCanTransfer;
|
|
||||||
constexpr std::uint32_t const tmfMPTCanMutateCanClawback = lsmfMPTCanMutateCanClawback;
|
|
||||||
constexpr std::uint32_t const tmfMPTCanMutateMetadata = lsmfMPTCanMutateMetadata;
|
|
||||||
constexpr std::uint32_t const tmfMPTCanMutateTransferFee = lsmfMPTCanMutateTransferFee;
|
|
||||||
constexpr std::uint32_t const tmfMPTokenIssuanceCreateMutableMask =
|
|
||||||
~(tmfMPTCanMutateCanLock | tmfMPTCanMutateRequireAuth | tmfMPTCanMutateCanEscrow | tmfMPTCanMutateCanTrade
|
|
||||||
| tmfMPTCanMutateCanTransfer | tmfMPTCanMutateCanClawback | tmfMPTCanMutateMetadata | tmfMPTCanMutateTransferFee);
|
|
||||||
|
|
||||||
// MPTokenAuthorize flags:
|
// MPTokenAuthorize flags:
|
||||||
constexpr std::uint32_t const tfMPTUnauthorize = 0x00000001;
|
constexpr std::uint32_t const tfMPTUnauthorize = 0x00000001;
|
||||||
constexpr std::uint32_t const tfMPTokenAuthorizeMask = ~(tfUniversal | tfMPTUnauthorize);
|
constexpr std::uint32_t const tfMPTokenAuthorizeMask = ~(tfUniversal | tfMPTUnauthorize);
|
||||||
@@ -178,25 +161,6 @@ constexpr std::uint32_t const tfMPTUnlock = 0x00000002;
|
|||||||
constexpr std::uint32_t const tfMPTokenIssuanceSetMask = ~(tfUniversal | tfMPTLock | tfMPTUnlock);
|
constexpr std::uint32_t const tfMPTokenIssuanceSetMask = ~(tfUniversal | tfMPTLock | tfMPTUnlock);
|
||||||
constexpr std::uint32_t const tfMPTokenIssuanceSetPermissionMask = ~(tfUniversal | tfMPTLock | tfMPTUnlock);
|
constexpr std::uint32_t const tfMPTokenIssuanceSetPermissionMask = ~(tfUniversal | tfMPTLock | tfMPTUnlock);
|
||||||
|
|
||||||
// MPTokenIssuanceSet MutableFlags:
|
|
||||||
// Set or Clear flags.
|
|
||||||
constexpr std::uint32_t const tmfMPTSetCanLock = 0x00000001;
|
|
||||||
constexpr std::uint32_t const tmfMPTClearCanLock = 0x00000002;
|
|
||||||
constexpr std::uint32_t const tmfMPTSetRequireAuth = 0x00000004;
|
|
||||||
constexpr std::uint32_t const tmfMPTClearRequireAuth = 0x00000008;
|
|
||||||
constexpr std::uint32_t const tmfMPTSetCanEscrow = 0x00000010;
|
|
||||||
constexpr std::uint32_t const tmfMPTClearCanEscrow = 0x00000020;
|
|
||||||
constexpr std::uint32_t const tmfMPTSetCanTrade = 0x00000040;
|
|
||||||
constexpr std::uint32_t const tmfMPTClearCanTrade = 0x00000080;
|
|
||||||
constexpr std::uint32_t const tmfMPTSetCanTransfer = 0x00000100;
|
|
||||||
constexpr std::uint32_t const tmfMPTClearCanTransfer = 0x00000200;
|
|
||||||
constexpr std::uint32_t const tmfMPTSetCanClawback = 0x00000400;
|
|
||||||
constexpr std::uint32_t const tmfMPTClearCanClawback = 0x00000800;
|
|
||||||
constexpr std::uint32_t const tmfMPTokenIssuanceSetMutableMask = ~(tmfMPTSetCanLock | tmfMPTClearCanLock |
|
|
||||||
tmfMPTSetRequireAuth | tmfMPTClearRequireAuth | tmfMPTSetCanEscrow | tmfMPTClearCanEscrow |
|
|
||||||
tmfMPTSetCanTrade | tmfMPTClearCanTrade | tmfMPTSetCanTransfer | tmfMPTClearCanTransfer |
|
|
||||||
tmfMPTSetCanClawback | tmfMPTClearCanClawback);
|
|
||||||
|
|
||||||
// MPTokenIssuanceDestroy flags:
|
// MPTokenIssuanceDestroy flags:
|
||||||
constexpr std::uint32_t const tfMPTokenIssuanceDestroyMask = ~tfUniversal;
|
constexpr std::uint32_t const tfMPTokenIssuanceDestroyMask = ~tfUniversal;
|
||||||
|
|
||||||
@@ -285,32 +249,6 @@ constexpr std::uint32_t tfIndependent = 0x00080000;
|
|||||||
constexpr std::uint32_t const tfBatchMask =
|
constexpr std::uint32_t const tfBatchMask =
|
||||||
~(tfUniversal | tfAllOrNothing | tfOnlyOne | tfUntilFailure | tfIndependent) | tfInnerBatchTxn;
|
~(tfUniversal | tfAllOrNothing | tfOnlyOne | tfUntilFailure | tfIndependent) | tfInnerBatchTxn;
|
||||||
|
|
||||||
// LoanSet and LoanPay flags:
|
|
||||||
// LoanSet: True, indicates the loan supports overpayments
|
|
||||||
// LoanPay: True, indicates any excess in this payment can be used
|
|
||||||
// as an overpayment. False, no overpayments will be taken.
|
|
||||||
constexpr std::uint32_t const tfLoanOverpayment = 0x00010000;
|
|
||||||
// LoanPay exclusive flags:
|
|
||||||
// tfLoanFullPayment: True, indicates that the payment is an early
|
|
||||||
// full payment. It must pay the entire loan including close
|
|
||||||
// interest and fees, or it will fail. False: Not a full payment.
|
|
||||||
constexpr std::uint32_t const tfLoanFullPayment = 0x00020000;
|
|
||||||
// tfLoanLatePayment: True, indicates that the payment is late,
|
|
||||||
// and includes late iterest and fees. If the loan is not late,
|
|
||||||
// it will fail. False: not a late payment. If the current payment
|
|
||||||
// is overdue, the transaction will fail.
|
|
||||||
constexpr std::uint32_t const tfLoanLatePayment = 0x00040000;
|
|
||||||
constexpr std::uint32_t const tfLoanSetMask = ~(tfUniversal |
|
|
||||||
tfLoanOverpayment);
|
|
||||||
constexpr std::uint32_t const tfLoanPayMask = ~(tfUniversal |
|
|
||||||
tfLoanOverpayment | tfLoanFullPayment | tfLoanLatePayment);
|
|
||||||
|
|
||||||
// LoanManage flags:
|
|
||||||
constexpr std::uint32_t const tfLoanDefault = 0x00010000;
|
|
||||||
constexpr std::uint32_t const tfLoanImpair = 0x00020000;
|
|
||||||
constexpr std::uint32_t const tfLoanUnimpair = 0x00040000;
|
|
||||||
constexpr std::uint32_t const tfLoanManageMask = ~(tfUniversal | tfLoanDefault | tfLoanImpair | tfLoanUnimpair);
|
|
||||||
|
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
} // namespace ripple
|
} // namespace ripple
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ enum TxType : std::uint16_t
|
|||||||
#pragma push_macro("TRANSACTION")
|
#pragma push_macro("TRANSACTION")
|
||||||
#undef TRANSACTION
|
#undef TRANSACTION
|
||||||
|
|
||||||
#define TRANSACTION(tag, value, ...) tag = value,
|
#define TRANSACTION(tag, value, name, delegatable, fields) tag = value,
|
||||||
|
|
||||||
#include <xrpl/protocol/detail/transactions.macro>
|
#include <xrpl/protocol/detail/transactions.macro>
|
||||||
|
|
||||||
|
|||||||
@@ -1,555 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of rippled: https://github.com/ripple/rippled
|
|
||||||
Copyright (c) 2019 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 PROTOCOL_UNITS_H_INCLUDED
|
|
||||||
#define PROTOCOL_UNITS_H_INCLUDED
|
|
||||||
|
|
||||||
#include <xrpl/basics/safe_cast.h>
|
|
||||||
#include <xrpl/beast/utility/Zero.h>
|
|
||||||
#include <xrpl/beast/utility/instrumentation.h>
|
|
||||||
#include <xrpl/json/json_value.h>
|
|
||||||
|
|
||||||
#include <boost/multiprecision/cpp_int.hpp>
|
|
||||||
#include <boost/operators.hpp>
|
|
||||||
|
|
||||||
#include <iosfwd>
|
|
||||||
#include <limits>
|
|
||||||
#include <optional>
|
|
||||||
|
|
||||||
namespace ripple {
|
|
||||||
|
|
||||||
namespace unit {
|
|
||||||
|
|
||||||
/** "drops" are the smallest divisible amount of XRP. This is what most
|
|
||||||
of the code uses. */
|
|
||||||
struct dropTag;
|
|
||||||
/** "fee levels" are used by the transaction queue to compare the relative
|
|
||||||
cost of transactions that require different levels of effort to process.
|
|
||||||
See also: src/ripple/app/misc/FeeEscalation.md#fee-level */
|
|
||||||
struct feelevelTag;
|
|
||||||
/** unitless values are plain scalars wrapped in a ValueUnit. They are
|
|
||||||
used for calculations in this header. */
|
|
||||||
struct unitlessTag;
|
|
||||||
|
|
||||||
/** Units to represent basis points (bips) and 1/10 basis points */
|
|
||||||
class BipsTag;
|
|
||||||
class TenthBipsTag;
|
|
||||||
|
|
||||||
// These names don't have to be too descriptive, because we're in the "unit"
|
|
||||||
// namespace.
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
concept Valid = std::is_class_v<T> && std::is_object_v<typename T::unit_type> &&
|
|
||||||
std::is_object_v<typename T::value_type>;
|
|
||||||
|
|
||||||
/** `Usable` is checked to ensure that only values with
|
|
||||||
known valid type tags can be used (sometimes transparently) in
|
|
||||||
non-unit contexts. At the time of implementation, this includes
|
|
||||||
all known tags, but more may be added in the future, and they
|
|
||||||
should not be added automatically unless determined to be
|
|
||||||
appropriate.
|
|
||||||
*/
|
|
||||||
template <class T>
|
|
||||||
concept Usable = Valid<T> &&
|
|
||||||
(std::is_same_v<typename T::unit_type, feelevelTag> ||
|
|
||||||
std::is_same_v<typename T::unit_type, unitlessTag> ||
|
|
||||||
std::is_same_v<typename T::unit_type, dropTag> ||
|
|
||||||
std::is_same_v<typename T::unit_type, BipsTag> ||
|
|
||||||
std::is_same_v<typename T::unit_type, TenthBipsTag>);
|
|
||||||
|
|
||||||
template <class Other, class VU>
|
|
||||||
concept Compatible = Valid<VU> && std::is_arithmetic_v<Other> &&
|
|
||||||
std::is_arithmetic_v<typename VU::value_type> &&
|
|
||||||
std::is_convertible_v<Other, typename VU::value_type>;
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
concept Integral = std::is_integral_v<T>;
|
|
||||||
|
|
||||||
template <class VU>
|
|
||||||
concept IntegralValue = Integral<typename VU::value_type>;
|
|
||||||
|
|
||||||
template <class VU1, class VU2>
|
|
||||||
concept CastableValue = IntegralValue<VU1> && IntegralValue<VU2> &&
|
|
||||||
std::is_same_v<typename VU1::unit_type, typename VU2::unit_type>;
|
|
||||||
|
|
||||||
template <class UnitTag, class T>
|
|
||||||
class ValueUnit : private boost::totally_ordered<ValueUnit<UnitTag, T>>,
|
|
||||||
private boost::additive<ValueUnit<UnitTag, T>>,
|
|
||||||
private boost::equality_comparable<ValueUnit<UnitTag, T>, T>,
|
|
||||||
private boost::dividable<ValueUnit<UnitTag, T>, T>,
|
|
||||||
private boost::modable<ValueUnit<UnitTag, T>, T>,
|
|
||||||
private boost::unit_steppable<ValueUnit<UnitTag, T>>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using unit_type = UnitTag;
|
|
||||||
using value_type = T;
|
|
||||||
|
|
||||||
private:
|
|
||||||
value_type value_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
ValueUnit() = default;
|
|
||||||
constexpr ValueUnit(ValueUnit const& other) = default;
|
|
||||||
constexpr ValueUnit&
|
|
||||||
operator=(ValueUnit const& other) = default;
|
|
||||||
|
|
||||||
constexpr explicit ValueUnit(beast::Zero) : value_(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr ValueUnit&
|
|
||||||
operator=(beast::Zero)
|
|
||||||
{
|
|
||||||
value_ = 0;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr explicit ValueUnit(value_type value) : value_(value)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr ValueUnit&
|
|
||||||
operator=(value_type value)
|
|
||||||
{
|
|
||||||
value_ = value;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Instances with the same unit, and a type that is
|
|
||||||
"safe" to convert to this one can be converted
|
|
||||||
implicitly */
|
|
||||||
template <Compatible<ValueUnit> Other>
|
|
||||||
constexpr ValueUnit(ValueUnit<unit_type, Other> const& value)
|
|
||||||
requires SafeToCast<Other, value_type>
|
|
||||||
: ValueUnit(safe_cast<value_type>(value.value()))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr ValueUnit
|
|
||||||
operator+(value_type const& rhs) const
|
|
||||||
{
|
|
||||||
return ValueUnit{value_ + rhs};
|
|
||||||
}
|
|
||||||
|
|
||||||
friend constexpr ValueUnit
|
|
||||||
operator+(value_type lhs, ValueUnit const& rhs)
|
|
||||||
{
|
|
||||||
// addition is commutative
|
|
||||||
return rhs + lhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr ValueUnit
|
|
||||||
operator-(value_type const& rhs) const
|
|
||||||
{
|
|
||||||
return ValueUnit{value_ - rhs};
|
|
||||||
}
|
|
||||||
|
|
||||||
friend constexpr ValueUnit
|
|
||||||
operator-(value_type lhs, ValueUnit const& rhs)
|
|
||||||
{
|
|
||||||
// subtraction is NOT commutative, but (lhs + (-rhs)) is addition, which
|
|
||||||
// is
|
|
||||||
return -rhs + lhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr ValueUnit
|
|
||||||
operator*(value_type const& rhs) const
|
|
||||||
{
|
|
||||||
return ValueUnit{value_ * rhs};
|
|
||||||
}
|
|
||||||
|
|
||||||
friend constexpr ValueUnit
|
|
||||||
operator*(value_type lhs, ValueUnit const& rhs)
|
|
||||||
{
|
|
||||||
// multiplication is commutative
|
|
||||||
return rhs * lhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr value_type
|
|
||||||
operator/(ValueUnit const& rhs) const
|
|
||||||
{
|
|
||||||
return value_ / rhs.value_;
|
|
||||||
}
|
|
||||||
|
|
||||||
ValueUnit&
|
|
||||||
operator+=(ValueUnit const& other)
|
|
||||||
{
|
|
||||||
value_ += other.value();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ValueUnit&
|
|
||||||
operator-=(ValueUnit const& other)
|
|
||||||
{
|
|
||||||
value_ -= other.value();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ValueUnit&
|
|
||||||
operator++()
|
|
||||||
{
|
|
||||||
++value_;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ValueUnit&
|
|
||||||
operator--()
|
|
||||||
{
|
|
||||||
--value_;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ValueUnit&
|
|
||||||
operator*=(value_type const& rhs)
|
|
||||||
{
|
|
||||||
value_ *= rhs;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ValueUnit&
|
|
||||||
operator/=(value_type const& rhs)
|
|
||||||
{
|
|
||||||
value_ /= rhs;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <Integral transparent = value_type>
|
|
||||||
ValueUnit&
|
|
||||||
operator%=(value_type const& rhs)
|
|
||||||
{
|
|
||||||
value_ %= rhs;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ValueUnit
|
|
||||||
operator-() const
|
|
||||||
{
|
|
||||||
static_assert(
|
|
||||||
std::is_signed_v<T>, "- operator illegal on unsigned value types");
|
|
||||||
return ValueUnit{-value_};
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr bool
|
|
||||||
operator==(ValueUnit const& other) const
|
|
||||||
{
|
|
||||||
return value_ == other.value_;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <Compatible<ValueUnit> Other>
|
|
||||||
constexpr bool
|
|
||||||
operator==(ValueUnit<unit_type, Other> const& other) const
|
|
||||||
{
|
|
||||||
return value_ == other.value();
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr bool
|
|
||||||
operator==(value_type other) const
|
|
||||||
{
|
|
||||||
return value_ == other;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <Compatible<ValueUnit> Other>
|
|
||||||
constexpr bool
|
|
||||||
operator!=(ValueUnit<unit_type, Other> const& other) const
|
|
||||||
{
|
|
||||||
return !operator==(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr bool
|
|
||||||
operator<(ValueUnit const& other) const
|
|
||||||
{
|
|
||||||
return value_ < other.value_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns true if the amount is not zero */
|
|
||||||
explicit constexpr
|
|
||||||
operator bool() const noexcept
|
|
||||||
{
|
|
||||||
return value_ != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Return the sign of the amount */
|
|
||||||
constexpr int
|
|
||||||
signum() const noexcept
|
|
||||||
{
|
|
||||||
return (value_ < 0) ? -1 : (value_ ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the number of drops */
|
|
||||||
// TODO: Move this to a new class, maybe with the old "TaggedFee" name
|
|
||||||
constexpr value_type
|
|
||||||
fee() const
|
|
||||||
{
|
|
||||||
return value_;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Other>
|
|
||||||
constexpr double
|
|
||||||
decimalFromReference(ValueUnit<unit_type, Other> reference) const
|
|
||||||
{
|
|
||||||
return static_cast<double>(value_) / reference.value();
|
|
||||||
}
|
|
||||||
|
|
||||||
// `Usable` is checked to ensure that only values with
|
|
||||||
// known valid type tags can be converted to JSON. At the time
|
|
||||||
// of implementation, that includes all known tags, but more may
|
|
||||||
// be added in the future.
|
|
||||||
Json::Value
|
|
||||||
jsonClipped() const
|
|
||||||
requires Usable<ValueUnit>
|
|
||||||
{
|
|
||||||
if constexpr (std::is_integral_v<value_type>)
|
|
||||||
{
|
|
||||||
using jsontype = std::conditional_t<
|
|
||||||
std::is_signed_v<value_type>,
|
|
||||||
Json::Int,
|
|
||||||
Json::UInt>;
|
|
||||||
|
|
||||||
constexpr auto min = std::numeric_limits<jsontype>::min();
|
|
||||||
constexpr auto max = std::numeric_limits<jsontype>::max();
|
|
||||||
|
|
||||||
if (value_ < min)
|
|
||||||
return min;
|
|
||||||
if (value_ > max)
|
|
||||||
return max;
|
|
||||||
return static_cast<jsontype>(value_);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return value_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the underlying value. Code SHOULD NOT call this
|
|
||||||
function unless the type has been abstracted away,
|
|
||||||
e.g. in a templated function.
|
|
||||||
*/
|
|
||||||
constexpr value_type
|
|
||||||
value() const
|
|
||||||
{
|
|
||||||
return value_;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend std::istream&
|
|
||||||
operator>>(std::istream& s, ValueUnit& val)
|
|
||||||
{
|
|
||||||
s >> val.value_;
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Output Values as just their numeric value.
|
|
||||||
template <class Char, class Traits, class UnitTag, class T>
|
|
||||||
std::basic_ostream<Char, Traits>&
|
|
||||||
operator<<(std::basic_ostream<Char, Traits>& os, ValueUnit<UnitTag, T> const& q)
|
|
||||||
{
|
|
||||||
return os << q.value();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class UnitTag, class T>
|
|
||||||
std::string
|
|
||||||
to_string(ValueUnit<UnitTag, T> const& amount)
|
|
||||||
{
|
|
||||||
return std::to_string(amount.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Source>
|
|
||||||
concept muldivSource = Valid<Source> &&
|
|
||||||
std::is_convertible_v<typename Source::value_type, std::uint64_t>;
|
|
||||||
|
|
||||||
template <class Dest>
|
|
||||||
concept muldivDest = muldivSource<Dest> && // Dest is also a source
|
|
||||||
std::is_convertible_v<std::uint64_t, typename Dest::value_type> &&
|
|
||||||
sizeof(typename Dest::value_type) >= sizeof(std::uint64_t);
|
|
||||||
|
|
||||||
template <class Source2, class Source1>
|
|
||||||
concept muldivSources = muldivSource<Source1> && muldivSource<Source2> &&
|
|
||||||
std::is_same_v<typename Source1::unit_type, typename Source2::unit_type>;
|
|
||||||
|
|
||||||
template <class Dest, class Source1, class Source2>
|
|
||||||
concept muldivable = muldivSources<Source1, Source2> && muldivDest<Dest>;
|
|
||||||
// Source and Dest can be the same by default
|
|
||||||
|
|
||||||
template <class Dest, class Source1, class Source2>
|
|
||||||
concept muldivCommutable = muldivable<Dest, Source1, Source2> &&
|
|
||||||
!std::is_same_v<typename Source1::unit_type, typename Dest::unit_type>;
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
ValueUnit<unitlessTag, T>
|
|
||||||
scalar(T value)
|
|
||||||
{
|
|
||||||
return ValueUnit<unitlessTag, T>{value};
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Source1, class Source2, unit::muldivable<Source1, Source2> Dest>
|
|
||||||
std::optional<Dest>
|
|
||||||
mulDivU(Source1 value, Dest mul, Source2 div)
|
|
||||||
{
|
|
||||||
// values can never be negative in any context.
|
|
||||||
if (value.value() < 0 || mul.value() < 0 || div.value() < 0)
|
|
||||||
{
|
|
||||||
// split the asserts so if one hits, the user can tell which
|
|
||||||
// without a debugger.
|
|
||||||
XRPL_ASSERT(
|
|
||||||
value.value() >= 0, "ripple::unit::mulDivU : minimum value input");
|
|
||||||
XRPL_ASSERT(
|
|
||||||
mul.value() >= 0, "ripple::unit::mulDivU : minimum mul input");
|
|
||||||
XRPL_ASSERT(
|
|
||||||
div.value() > 0, "ripple::unit::mulDivU : minimum div input");
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
using desttype = typename Dest::value_type;
|
|
||||||
constexpr auto max = std::numeric_limits<desttype>::max();
|
|
||||||
|
|
||||||
// Shortcuts, since these happen a lot in the real world
|
|
||||||
if (value == div)
|
|
||||||
return mul;
|
|
||||||
if (mul.value() == div.value())
|
|
||||||
{
|
|
||||||
if (value.value() > max)
|
|
||||||
return std::nullopt;
|
|
||||||
return Dest{static_cast<desttype>(value.value())};
|
|
||||||
}
|
|
||||||
|
|
||||||
using namespace boost::multiprecision;
|
|
||||||
|
|
||||||
uint128_t product;
|
|
||||||
product = multiply(
|
|
||||||
product,
|
|
||||||
static_cast<std::uint64_t>(value.value()),
|
|
||||||
static_cast<std::uint64_t>(mul.value()));
|
|
||||||
|
|
||||||
auto quotient = product / div.value();
|
|
||||||
|
|
||||||
if (quotient > max)
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
return Dest{static_cast<desttype>(quotient)};
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace unit
|
|
||||||
|
|
||||||
// Fee Levels
|
|
||||||
template <class T>
|
|
||||||
using FeeLevel = unit::ValueUnit<unit::feelevelTag, T>;
|
|
||||||
using FeeLevel64 = FeeLevel<std::uint64_t>;
|
|
||||||
using FeeLevelDouble = FeeLevel<double>;
|
|
||||||
|
|
||||||
// Basis points (Bips)
|
|
||||||
template <class T>
|
|
||||||
using Bips = unit::ValueUnit<unit::BipsTag, T>;
|
|
||||||
using Bips16 = Bips<std::uint16_t>;
|
|
||||||
using Bips32 = Bips<std::uint32_t>;
|
|
||||||
template <class T>
|
|
||||||
using TenthBips = unit::ValueUnit<unit::TenthBipsTag, T>;
|
|
||||||
using TenthBips16 = TenthBips<std::uint16_t>;
|
|
||||||
using TenthBips32 = TenthBips<std::uint32_t>;
|
|
||||||
|
|
||||||
template <class Source1, class Source2, unit::muldivable<Source1, Source2> Dest>
|
|
||||||
std::optional<Dest>
|
|
||||||
mulDiv(Source1 value, Dest mul, Source2 div)
|
|
||||||
{
|
|
||||||
return unit::mulDivU(value, mul, div);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <
|
|
||||||
class Source1,
|
|
||||||
class Source2,
|
|
||||||
unit::muldivCommutable<Source1, Source2> Dest>
|
|
||||||
std::optional<Dest>
|
|
||||||
mulDiv(Dest value, Source1 mul, Source2 div)
|
|
||||||
{
|
|
||||||
// Multiplication is commutative
|
|
||||||
return unit::mulDivU(mul, value, div);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <unit::muldivDest Dest>
|
|
||||||
std::optional<Dest>
|
|
||||||
mulDiv(std::uint64_t value, Dest mul, std::uint64_t div)
|
|
||||||
{
|
|
||||||
// Give the scalars a non-tag so the
|
|
||||||
// unit-handling version gets called.
|
|
||||||
return unit::mulDivU(unit::scalar(value), mul, unit::scalar(div));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <unit::muldivDest Dest>
|
|
||||||
std::optional<Dest>
|
|
||||||
mulDiv(Dest value, std::uint64_t mul, std::uint64_t div)
|
|
||||||
{
|
|
||||||
// Multiplication is commutative
|
|
||||||
return mulDiv(mul, value, div);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <unit::muldivSource Source1, unit::muldivSources<Source1> Source2>
|
|
||||||
std::optional<std::uint64_t>
|
|
||||||
mulDiv(Source1 value, std::uint64_t mul, Source2 div)
|
|
||||||
{
|
|
||||||
// Give the scalars a dimensionless unit so the
|
|
||||||
// unit-handling version gets called.
|
|
||||||
auto unitresult = unit::mulDivU(value, unit::scalar(mul), div);
|
|
||||||
|
|
||||||
if (!unitresult)
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
return unitresult->value();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <unit::muldivSource Source1, unit::muldivSources<Source1> Source2>
|
|
||||||
std::optional<std::uint64_t>
|
|
||||||
mulDiv(std::uint64_t value, Source1 mul, Source2 div)
|
|
||||||
{
|
|
||||||
// Multiplication is commutative
|
|
||||||
return mulDiv(mul, value, div);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <unit::IntegralValue Dest, unit::CastableValue<Dest> Src>
|
|
||||||
constexpr Dest
|
|
||||||
safe_cast(Src s) noexcept
|
|
||||||
{
|
|
||||||
// Dest may not have an explicit value constructor
|
|
||||||
return Dest{safe_cast<typename Dest::value_type>(s.value())};
|
|
||||||
}
|
|
||||||
|
|
||||||
template <unit::IntegralValue Dest, unit::Integral Src>
|
|
||||||
constexpr Dest
|
|
||||||
safe_cast(Src s) noexcept
|
|
||||||
{
|
|
||||||
// Dest may not have an explicit value constructor
|
|
||||||
return Dest{safe_cast<typename Dest::value_type>(s)};
|
|
||||||
}
|
|
||||||
|
|
||||||
template <unit::IntegralValue Dest, unit::CastableValue<Dest> Src>
|
|
||||||
constexpr Dest
|
|
||||||
unsafe_cast(Src s) noexcept
|
|
||||||
{
|
|
||||||
// Dest may not have an explicit value constructor
|
|
||||||
return Dest{unsafe_cast<typename Dest::value_type>(s.value())};
|
|
||||||
}
|
|
||||||
|
|
||||||
template <unit::IntegralValue Dest, unit::Integral Src>
|
|
||||||
constexpr Dest
|
|
||||||
unsafe_cast(Src s) noexcept
|
|
||||||
{
|
|
||||||
// Dest may not have an explicit value constructor
|
|
||||||
return Dest{unsafe_cast<typename Dest::value_type>(s)};
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ripple
|
|
||||||
|
|
||||||
#endif // PROTOCOL_UNITS_H_INCLUDED
|
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
#include <xrpl/basics/contract.h>
|
#include <xrpl/basics/contract.h>
|
||||||
#include <xrpl/beast/utility/Zero.h>
|
#include <xrpl/beast/utility/Zero.h>
|
||||||
#include <xrpl/json/json_value.h>
|
#include <xrpl/json/json_value.h>
|
||||||
#include <xrpl/protocol/Units.h>
|
#include <xrpl/protocol/FeeUnits.h>
|
||||||
|
|
||||||
#include <boost/multiprecision/cpp_int.hpp>
|
#include <boost/multiprecision/cpp_int.hpp>
|
||||||
#include <boost/operators.hpp>
|
#include <boost/operators.hpp>
|
||||||
@@ -42,7 +42,7 @@ class XRPAmount : private boost::totally_ordered<XRPAmount>,
|
|||||||
private boost::additive<XRPAmount, std::int64_t>
|
private boost::additive<XRPAmount, std::int64_t>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using unit_type = unit::dropTag;
|
using unit_type = feeunit::dropTag;
|
||||||
using value_type = std::int64_t;
|
using value_type = std::int64_t;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -129,12 +129,10 @@ 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
|
// 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.
|
// the a null set of numbers to be zero, so the remainder is also zero.
|
||||||
// LCOV_EXCL_START
|
|
||||||
UNREACHABLE(
|
UNREACHABLE(
|
||||||
"ripple::b58_fast::detail::inplace_bigint_div_rem : empty "
|
"ripple::b58_fast::detail::inplace_bigint_div_rem : empty "
|
||||||
"numerator");
|
"numerator");
|
||||||
return 0;
|
return 0;
|
||||||
// LCOV_EXCL_STOP
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto to_u128 = [](std::uint64_t high,
|
auto to_u128 = [](std::uint64_t high,
|
||||||
|
|||||||
@@ -27,29 +27,22 @@
|
|||||||
#error "undefined macro: XRPL_RETIRE"
|
#error "undefined macro: XRPL_RETIRE"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
|
|
||||||
// Add new amendments to the top of this list.
|
// Add new amendments to the top of this list.
|
||||||
// Keep it sorted in reverse chronological order.
|
// 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 (Cleanup3_1_3, Supported::yes, VoteBehavior::DefaultYes)
|
XRPL_FEATURE(Subscription, Supported::no, VoteBehavior::DefaultNo)
|
||||||
XRPL_FIX (BatchInnerSigs, Supported::no, VoteBehavior::DefaultNo)
|
XRPL_FIX (PriceOracleOrder, Supported::no, VoteBehavior::DefaultNo)
|
||||||
XRPL_FEATURE(LendingProtocol, Supported::yes, VoteBehavior::DefaultNo)
|
XRPL_FIX (MPTDeliveredAmount, Supported::no, VoteBehavior::DefaultNo)
|
||||||
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::yes, VoteBehavior::DefaultNo)
|
|
||||||
XRPL_FIX (AMMClawbackRounding, Supported::yes, VoteBehavior::DefaultNo)
|
XRPL_FIX (AMMClawbackRounding, Supported::yes, VoteBehavior::DefaultNo)
|
||||||
XRPL_FEATURE(TokenEscrow, Supported::yes, VoteBehavior::DefaultNo)
|
XRPL_FEATURE(TokenEscrow, Supported::yes, VoteBehavior::DefaultNo)
|
||||||
XRPL_FIX (EnforceNFTokenTrustlineV2, Supported::yes, VoteBehavior::DefaultNo)
|
XRPL_FIX (EnforceNFTokenTrustlineV2, Supported::yes, VoteBehavior::DefaultNo)
|
||||||
XRPL_FIX (AMMv1_3, Supported::yes, VoteBehavior::DefaultNo)
|
XRPL_FIX (AMMv1_3, Supported::yes, VoteBehavior::DefaultNo)
|
||||||
XRPL_FEATURE(PermissionedDEX, Supported::yes, VoteBehavior::DefaultNo)
|
XRPL_FEATURE(PermissionedDEX, Supported::yes, VoteBehavior::DefaultNo)
|
||||||
XRPL_FEATURE(Batch, Supported::no, VoteBehavior::DefaultNo)
|
XRPL_FEATURE(Batch, Supported::yes, VoteBehavior::DefaultNo)
|
||||||
XRPL_FEATURE(SingleAssetVault, Supported::yes, VoteBehavior::DefaultNo)
|
XRPL_FEATURE(SingleAssetVault, Supported::no, VoteBehavior::DefaultNo)
|
||||||
XRPL_FEATURE(PermissionDelegation, Supported::no, VoteBehavior::DefaultNo)
|
XRPL_FEATURE(PermissionDelegation, Supported::yes, VoteBehavior::DefaultNo)
|
||||||
XRPL_FIX (PayChanCancelAfter, Supported::yes, VoteBehavior::DefaultNo)
|
XRPL_FIX (PayChanCancelAfter, Supported::yes, VoteBehavior::DefaultNo)
|
||||||
// Check flags in Credential transactions
|
// Check flags in Credential transactions
|
||||||
XRPL_FIX (InvalidTxFlags, Supported::yes, VoteBehavior::DefaultNo)
|
XRPL_FIX (InvalidTxFlags, Supported::yes, VoteBehavior::DefaultNo)
|
||||||
@@ -160,5 +153,3 @@ XRPL_RETIRE(fix1512)
|
|||||||
XRPL_RETIRE(fix1523)
|
XRPL_RETIRE(fix1523)
|
||||||
XRPL_RETIRE(fix1528)
|
XRPL_RETIRE(fix1528)
|
||||||
XRPL_RETIRE(FlowCross)
|
XRPL_RETIRE(FlowCross)
|
||||||
|
|
||||||
// clang-format on
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user