Compare commits

..

1 Commits

Author SHA1 Message Date
JCW
85eb901d9d Add rust library
Signed-off-by: JCW <a1q123456@users.noreply.github.com>
2025-09-11 17:55:53 +01:00
560 changed files with 11239 additions and 26196 deletions

View File

@@ -33,6 +33,5 @@ slack_app: false
ignore:
- "src/test/"
- "src/tests/"
- "include/xrpl/beast/test/"
- "include/xrpl/beast/unit_test/"

View File

@@ -10,40 +10,24 @@ inputs:
build_type:
description: 'The build type to use ("Debug", "Release").'
required: true
build_nproc:
description: "The number of processors to use for building."
required: true
force_build:
description: 'Force building of all dependencies ("true", "false").'
required: false
default: "false"
log_verbosity:
description: "The logging verbosity."
required: false
default: "verbose"
runs:
using: composite
steps:
- name: Install Conan dependencies
shell: bash
env:
BUILD_DIR: ${{ inputs.build_dir }}
BUILD_NPROC: ${{ inputs.build_nproc }}
BUILD_OPTION: ${{ inputs.force_build == 'true' && '*' || 'missing' }}
BUILD_TYPE: ${{ inputs.build_type }}
LOG_VERBOSITY: ${{ inputs.log_verbosity }}
run: |
echo 'Installing dependencies.'
mkdir -p "${BUILD_DIR}"
cd "${BUILD_DIR}"
mkdir -p ${{ inputs.build_dir }}
cd ${{ inputs.build_dir }}
conan install \
--output-folder . \
--build="${BUILD_OPTION}" \
--options:host='&:tests=True' \
--options:host='&:xrpld=True' \
--settings:all build_type="${BUILD_TYPE}" \
--conf:all tools.build:jobs=${BUILD_NPROC} \
--conf:all tools.build:verbosity="${LOG_VERBOSITY}" \
--conf:all tools.compilation:verbosity="${LOG_VERBOSITY}" \
--build ${{ inputs.force_build == 'true' && '"*"' || 'missing' }} \
--options:host '&:tests=True' \
--options:host '&:xrpld=True' \
--settings:all build_type=${{ inputs.build_type }} \
..

96
.github/actions/build-test/action.yml vendored Normal file
View 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

View File

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

View File

@@ -35,12 +35,9 @@ runs:
- name: Set up Conan remote
shell: bash
env:
CONAN_REMOTE_NAME: ${{ inputs.conan_remote_name }}
CONAN_REMOTE_URL: ${{ inputs.conan_remote_url }}
run: |
echo "Adding Conan remote '${CONAN_REMOTE_NAME}' at '${CONAN_REMOTE_URL}'."
conan remote add --index 0 --force "${CONAN_REMOTE_NAME}" "${CONAN_REMOTE_URL}"
echo "Adding Conan remote '${{ inputs.conan_remote_name }}' at ${{ inputs.conan_remote_url }}."
conan remote add --index 0 --force ${{ inputs.conan_remote_name }} ${{ inputs.conan_remote_url }}
echo 'Listing Conan remotes.'
conan remote list

View File

@@ -72,15 +72,15 @@ It generates many files of [results](results):
desired as described above. In a perfect repo, this file will be
empty.
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.
- [`ordering.txt`](results/ordering.txt): A list showing relationships
between modules where there are no loops as they actually exist, as
opposed to how they are desired as described above.
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.
- [`levelization.yml`](../../workflows/reusable-check-levelization.yml)
- [`levelization.yml`](../../workflows/check-levelization.yml)
Github Actions workflow to test that levelization loops haven't
changed. Unfortunately, if changes are detected, it can't tell if
they are improvements or not, so if you have resolved any issues or

View File

@@ -7,6 +7,9 @@ Loop: test.jtx test.unit_test
Loop: xrpld.app xrpld.core
xrpld.app > xrpld.core
Loop: xrpld.app xrpld.ledger
xrpld.app > xrpld.ledger
Loop: xrpld.app xrpld.overlay
xrpld.overlay > xrpld.app
@@ -17,7 +20,7 @@ Loop: xrpld.app xrpld.rpc
xrpld.rpc > xrpld.app
Loop: xrpld.app xrpld.shamap
xrpld.shamap ~= xrpld.app
xrpld.app > xrpld.shamap
Loop: xrpld.core xrpld.perflog
xrpld.perflog == xrpld.core

View File

@@ -2,16 +2,8 @@ libxrpl.basics > xrpl.basics
libxrpl.crypto > xrpl.basics
libxrpl.json > xrpl.basics
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.net
libxrpl.nodestore > xrpl.basics
libxrpl.nodestore > xrpl.json
libxrpl.nodestore > xrpl.nodestore
libxrpl.nodestore > xrpl.protocol
libxrpl.protocol > xrpl.basics
libxrpl.protocol > xrpl.json
libxrpl.protocol > xrpl.protocol
@@ -22,9 +14,6 @@ libxrpl.server > xrpl.basics
libxrpl.server > xrpl.json
libxrpl.server > xrpl.protocol
libxrpl.server > xrpl.server
libxrpl.shamap > xrpl.basics
libxrpl.shamap > xrpl.protocol
libxrpl.shamap > xrpl.shamap
test.app > test.jtx
test.app > test.rpc
test.app > test.toplevel
@@ -32,11 +21,11 @@ test.app > test.unit_test
test.app > xrpl.basics
test.app > xrpld.app
test.app > xrpld.core
test.app > xrpld.ledger
test.app > xrpld.nodestore
test.app > xrpld.overlay
test.app > xrpld.rpc
test.app > xrpl.json
test.app > xrpl.ledger
test.app > xrpl.nodestore
test.app > xrpl.protocol
test.app > xrpl.resource
test.basics > test.jtx
@@ -55,8 +44,8 @@ test.consensus > test.unit_test
test.consensus > xrpl.basics
test.consensus > xrpld.app
test.consensus > xrpld.consensus
test.consensus > xrpld.ledger
test.consensus > xrpl.json
test.consensus > xrpl.ledger
test.core > test.jtx
test.core > test.toplevel
test.core > test.unit_test
@@ -74,9 +63,9 @@ test.json > xrpl.json
test.jtx > xrpl.basics
test.jtx > xrpld.app
test.jtx > xrpld.core
test.jtx > xrpld.ledger
test.jtx > xrpld.rpc
test.jtx > xrpl.json
test.jtx > xrpl.ledger
test.jtx > xrpl.net
test.jtx > xrpl.protocol
test.jtx > xrpl.resource
@@ -86,14 +75,15 @@ test.ledger > test.toplevel
test.ledger > xrpl.basics
test.ledger > xrpld.app
test.ledger > xrpld.core
test.ledger > xrpl.ledger
test.ledger > xrpld.ledger
test.ledger > xrpl.protocol
test.nodestore > test.jtx
test.nodestore > test.toplevel
test.nodestore > test.unit_test
test.nodestore > xrpl.basics
test.nodestore > xrpld.core
test.nodestore > xrpl.nodestore
test.nodestore > xrpld.nodestore
test.nodestore > xrpld.unity
test.overlay > test.jtx
test.overlay > test.toplevel
test.overlay > test.unit_test
@@ -101,8 +91,8 @@ test.overlay > xrpl.basics
test.overlay > xrpld.app
test.overlay > xrpld.overlay
test.overlay > xrpld.peerfinder
test.overlay > xrpld.shamap
test.overlay > xrpl.protocol
test.overlay > xrpl.shamap
test.peerfinder > test.beast
test.peerfinder > test.unit_test
test.peerfinder > xrpl.basics
@@ -137,21 +127,15 @@ test.server > xrpl.json
test.server > xrpl.server
test.shamap > test.unit_test
test.shamap > xrpl.basics
test.shamap > xrpl.nodestore
test.shamap > xrpld.nodestore
test.shamap > xrpld.shamap
test.shamap > xrpl.protocol
test.shamap > xrpl.shamap
test.toplevel > test.csf
test.toplevel > xrpl.json
test.unit_test > xrpl.basics
tests.libxrpl > xrpl.basics
tests.libxrpl > xrpl.json
tests.libxrpl > xrpl.net
xrpl.json > xrpl.basics
xrpl.ledger > xrpl.basics
xrpl.ledger > xrpl.protocol
xrpl.net > xrpl.basics
xrpl.nodestore > xrpl.basics
xrpl.nodestore > xrpl.protocol
xrpl.protocol > xrpl.basics
xrpl.protocol > xrpl.json
xrpl.resource > xrpl.basics
@@ -160,21 +144,16 @@ xrpl.resource > xrpl.protocol
xrpl.server > xrpl.basics
xrpl.server > xrpl.json
xrpl.server > xrpl.protocol
xrpl.shamap > xrpl.basics
xrpl.shamap > xrpl.nodestore
xrpl.shamap > xrpl.protocol
xrpld.app > test.unit_test
xrpld.app > xrpl.basics
xrpld.app > xrpld.conditions
xrpld.app > xrpld.consensus
xrpld.app > xrpld.nodestore
xrpld.app > xrpld.perflog
xrpld.app > xrpl.json
xrpld.app > xrpl.ledger
xrpld.app > xrpl.net
xrpld.app > xrpl.nodestore
xrpld.app > xrpl.protocol
xrpld.app > xrpl.resource
xrpld.app > xrpl.shamap
xrpld.conditions > xrpl.basics
xrpld.conditions > xrpl.protocol
xrpld.consensus > xrpl.basics
@@ -184,6 +163,14 @@ xrpld.core > xrpl.basics
xrpld.core > xrpl.json
xrpld.core > xrpl.net
xrpld.core > xrpl.protocol
xrpld.ledger > xrpl.basics
xrpld.ledger > xrpl.json
xrpld.ledger > xrpl.protocol
xrpld.nodestore > xrpl.basics
xrpld.nodestore > xrpld.core
xrpld.nodestore > xrpld.unity
xrpld.nodestore > xrpl.json
xrpld.nodestore > xrpl.protocol
xrpld.overlay > xrpl.basics
xrpld.overlay > xrpld.core
xrpld.overlay > xrpld.peerfinder
@@ -199,11 +186,13 @@ xrpld.perflog > xrpl.basics
xrpld.perflog > xrpl.json
xrpld.rpc > xrpl.basics
xrpld.rpc > xrpld.core
xrpld.rpc > xrpld.ledger
xrpld.rpc > xrpld.nodestore
xrpld.rpc > xrpl.json
xrpld.rpc > xrpl.ledger
xrpld.rpc > xrpl.net
xrpld.rpc > xrpl.nodestore
xrpld.rpc > xrpl.protocol
xrpld.rpc > xrpl.resource
xrpld.rpc > xrpl.server
xrpld.shamap > xrpl.shamap
xrpld.shamap > xrpl.basics
xrpld.shamap > xrpld.nodestore
xrpld.shamap > xrpl.protocol

View File

@@ -74,14 +74,14 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
continue
# RHEL:
# - 9 using GCC 12: Debug and Unity on linux/amd64.
# - 10 using Clang: Release and no Unity on linux/amd64.
# - 9.4 using GCC 12: Debug and Unity on linux/amd64.
# - 9.6 using Clang: Release and no Unity on linux/amd64.
if os['distro_name'] == 'rhel':
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':
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':
skip = False
if skip:
@@ -162,7 +162,7 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
'config_name': config_name,
'cmake_args': cmake_args,
'cmake_target': cmake_target,
'build_only': build_only,
'build_only': 'true' if build_only else 'false',
'build_type': build_type,
'os': os,
'architecture': architecture,

View File

@@ -14,169 +14,139 @@
"distro_name": "debian",
"distro_version": "bookworm",
"compiler_name": "gcc",
"compiler_version": "12",
"image_sha": "97ba375"
"compiler_version": "12"
},
{
"distro_name": "debian",
"distro_version": "bookworm",
"compiler_name": "gcc",
"compiler_version": "13",
"image_sha": "97ba375"
"compiler_version": "13"
},
{
"distro_name": "debian",
"distro_version": "bookworm",
"compiler_name": "gcc",
"compiler_version": "14",
"image_sha": "97ba375"
"compiler_version": "14"
},
{
"distro_name": "debian",
"distro_version": "bookworm",
"compiler_name": "gcc",
"compiler_version": "15",
"image_sha": "97ba375"
"compiler_version": "15"
},
{
"distro_name": "debian",
"distro_version": "bookworm",
"compiler_name": "clang",
"compiler_version": "16",
"image_sha": "97ba375"
"compiler_version": "16"
},
{
"distro_name": "debian",
"distro_version": "bookworm",
"compiler_name": "clang",
"compiler_version": "17",
"image_sha": "97ba375"
"compiler_version": "17"
},
{
"distro_name": "debian",
"distro_version": "bookworm",
"compiler_name": "clang",
"compiler_version": "18",
"image_sha": "97ba375"
"compiler_version": "18"
},
{
"distro_name": "debian",
"distro_version": "bookworm",
"compiler_name": "clang",
"compiler_version": "19",
"image_sha": "97ba375"
"compiler_version": "19"
},
{
"distro_name": "debian",
"distro_version": "bookworm",
"compiler_name": "clang",
"compiler_version": "20",
"image_sha": "97ba375"
"compiler_version": "20"
},
{
"distro_name": "rhel",
"distro_version": "8",
"distro_version": "9.4",
"compiler_name": "gcc",
"compiler_version": "14",
"image_sha": "97ba375"
"compiler_version": "12"
},
{
"distro_name": "rhel",
"distro_version": "8",
"distro_version": "9.4",
"compiler_name": "gcc",
"compiler_version": "13"
},
{
"distro_name": "rhel",
"distro_version": "9.4",
"compiler_name": "gcc",
"compiler_version": "14"
},
{
"distro_name": "rhel",
"distro_version": "9.6",
"compiler_name": "gcc",
"compiler_version": "13"
},
{
"distro_name": "rhel",
"distro_version": "9.6",
"compiler_name": "gcc",
"compiler_version": "14"
},
{
"distro_name": "rhel",
"distro_version": "9.4",
"compiler_name": "clang",
"compiler_version": "any",
"image_sha": "97ba375"
"compiler_version": "any"
},
{
"distro_name": "rhel",
"distro_version": "9",
"compiler_name": "gcc",
"compiler_version": "12",
"image_sha": "97ba375"
},
{
"distro_name": "rhel",
"distro_version": "9",
"compiler_name": "gcc",
"compiler_version": "13",
"image_sha": "97ba375"
},
{
"distro_name": "rhel",
"distro_version": "9",
"compiler_name": "gcc",
"compiler_version": "14",
"image_sha": "97ba375"
},
{
"distro_name": "rhel",
"distro_version": "9",
"distro_version": "9.6",
"compiler_name": "clang",
"compiler_version": "any",
"image_sha": "97ba375"
},
{
"distro_name": "rhel",
"distro_version": "10",
"compiler_name": "gcc",
"compiler_version": "14",
"image_sha": "97ba375"
},
{
"distro_name": "rhel",
"distro_version": "10",
"compiler_name": "clang",
"compiler_version": "any",
"image_sha": "97ba375"
"compiler_version": "any"
},
{
"distro_name": "ubuntu",
"distro_version": "jammy",
"compiler_name": "gcc",
"compiler_version": "12",
"image_sha": "97ba375"
"compiler_version": "12"
},
{
"distro_name": "ubuntu",
"distro_version": "noble",
"compiler_name": "gcc",
"compiler_version": "13",
"image_sha": "97ba375"
"compiler_version": "13"
},
{
"distro_name": "ubuntu",
"distro_version": "noble",
"compiler_name": "gcc",
"compiler_version": "14",
"image_sha": "97ba375"
"compiler_version": "14"
},
{
"distro_name": "ubuntu",
"distro_version": "noble",
"compiler_name": "clang",
"compiler_version": "16",
"image_sha": "97ba375"
"compiler_version": "16"
},
{
"distro_name": "ubuntu",
"distro_version": "noble",
"compiler_name": "clang",
"compiler_version": "17",
"image_sha": "97ba375"
"compiler_version": "17"
},
{
"distro_name": "ubuntu",
"distro_version": "noble",
"compiler_name": "clang",
"compiler_version": "18",
"image_sha": "97ba375"
"compiler_version": "18"
},
{
"distro_name": "ubuntu",
"distro_version": "noble",
"compiler_name": "clang",
"compiler_version": "19",
"image_sha": "97ba375"
"compiler_version": "19"
}
],
"build_type": ["Debug", "Release"],

View File

@@ -10,8 +10,7 @@
"distro_name": "macos",
"distro_version": "",
"compiler_name": "",
"compiler_version": "",
"image_sha": ""
"compiler_version": ""
}
],
"build_type": ["Debug", "Release"],

View File

@@ -2,7 +2,7 @@
"architecture": [
{
"platform": "windows/amd64",
"runner": ["self-hosted", "Windows", "devbox"]
"runner": ["windows-latest"]
}
],
"os": [
@@ -10,8 +10,7 @@
"distro_name": "windows",
"distro_version": "",
"compiler_name": "",
"compiler_version": "",
"image_sha": ""
"compiler_version": ""
}
],
"build_type": ["Debug", "Release"],

146
.github/workflows/build-test.yml vendored Normal file
View 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 }}

View File

@@ -40,52 +40,47 @@ jobs:
upload:
if: ${{ github.event.pull_request.head.repo.full_name == github.repository }}
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:
- name: Checkout repository
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
- name: Generate outputs
id: generate
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
run: |
echo 'Generating user and channel.'
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 "version=$(cat src/libxrpl/protocol/BuildInfo.cpp | grep "versionString =" | awk -F '"' '{print $2}')" >> "${GITHUB_OUTPUT}"
- name: Calculate conan reference
id: conan_ref
run: |
echo "conan_ref=${{ steps.generate.outputs.version }}@${{ steps.generate.outputs.user }}/${{ steps.generate.outputs.channel }}" >> "${GITHUB_OUTPUT}"
- name: Set up Conan
uses: ./.github/actions/setup-conan
with:
conan_remote_name: ${{ inputs.conan_remote_name }}
conan_remote_url: ${{ inputs.conan_remote_url }}
- name: Log into Conan remote
env:
CONAN_REMOTE_NAME: ${{ inputs.conan_remote_name }}
run: conan remote login "${CONAN_REMOTE_NAME}" "${{ secrets.conan_remote_username }}" --password "${{ secrets.conan_remote_password }}"
run: conan remote login ${{ inputs.conan_remote_name }} "${{ secrets.conan_remote_username }}" --password "${{ secrets.conan_remote_password }}"
- name: Upload package
env:
CONAN_REMOTE_NAME: ${{ inputs.conan_remote_name }}
run: |
conan export --user=${{ steps.generate.outputs.user }} --channel=${{ steps.generate.outputs.channel }} .
conan upload --confirm --check --remote="${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:
conan_ref: ${{ steps.conan_ref.outputs.conan_ref }}
notify:
needs: upload
runs-on: ubuntu-latest
env:
GH_TOKEN: ${{ secrets.clio_notify_token }}
steps:
- name: Notify Clio
env:
GH_TOKEN: ${{ secrets.clio_notify_token }}
PR_URL: ${{ github.event.pull_request.html_url }}
run: |
gh api --method POST -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" \
/repos/xrplf/clio/dispatches -f "event_type=check_libxrpl" \
-F "client_payload[conan_ref]=${{ needs.upload.outputs.conan_ref }}" \
-F "client_payload[pr_url]=${PR_URL}"
-F "client_payload[pr_url]=${{ github.event.pull_request.html_url }}"

View File

@@ -50,8 +50,8 @@ jobs:
files: |
# These paths are unique to `on-pr.yml`.
.github/scripts/levelization/**
.github/workflows/reusable-check-levelization.yml
.github/workflows/reusable-notify-clio.yml
.github/workflows/check-levelization.yml
.github/workflows/notify-clio.yml
.github/workflows/on-pr.yml
# Keep the paths below in sync with those in `on-trigger.yml`.
@@ -59,11 +59,8 @@ jobs:
.github/actions/build-test/**
.github/actions/setup-conan/**
.github/scripts/strategy-matrix/**
.github/workflows/reusable-build.yml
.github/workflows/reusable-build-test-config.yml
.github/workflows/reusable-build-test.yml
.github/workflows/build-test.yml
.github/workflows/reusable-strategy-matrix.yml
.github/workflows/reusable-test.yml
.codecov.yml
cmake/**
conan/**
@@ -95,28 +92,27 @@ jobs:
check-levelization:
needs: should-run
if: ${{ needs.should-run.outputs.go == 'true' }}
uses: ./.github/workflows/reusable-check-levelization.yml
if: needs.should-run.outputs.go == 'true'
uses: ./.github/workflows/check-levelization.yml
build-test:
needs: should-run
if: ${{ needs.should-run.outputs.go == 'true' }}
uses: ./.github/workflows/reusable-build-test.yml
if: needs.should-run.outputs.go == 'true'
uses: ./.github/workflows/build-test.yml
strategy:
fail-fast: false
matrix:
os: [linux, macos, windows]
with:
os: ${{ matrix.os }}
secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
codecov_token: ${{ secrets.CODECOV_TOKEN }}
notify-clio:
needs:
- should-run
- build-test
if: ${{ needs.should-run.outputs.go == 'true' && contains(fromJSON('["release", "master"]'), github.ref_name) }}
uses: ./.github/workflows/reusable-notify-clio.yml
if: needs.should-run.outputs.go == 'true'
uses: ./.github/workflows/notify-clio.yml
secrets:
clio_notify_token: ${{ secrets.CLIO_NOTIFY_TOKEN }}
conan_remote_username: ${{ secrets.CONAN_REMOTE_USERNAME }}

View File

@@ -9,12 +9,12 @@ name: Trigger
on:
push:
branches:
- "develop"
- "release*"
- "master"
- develop
- release
- master
paths:
# These paths are unique to `on-trigger.yml`.
- ".github/workflows/reusable-check-missing-commits.yml"
- ".github/workflows/check-missing-commits.yml"
- ".github/workflows/on-trigger.yml"
- ".github/workflows/publish-docs.yml"
@@ -23,11 +23,8 @@ on:
- ".github/actions/build-test/**"
- ".github/actions/setup-conan/**"
- ".github/scripts/strategy-matrix/**"
- ".github/workflows/reusable-build.yml"
- ".github/workflows/reusable-build-test-config.yml"
- ".github/workflows/reusable-build-test.yml"
- ".github/workflows/build-test.yml"
- ".github/workflows/reusable-strategy-matrix.yml"
- ".github/workflows/reusable-test.yml"
- ".codecov.yml"
- "cmake/**"
- "conan/**"
@@ -46,16 +43,25 @@ on:
schedule:
- 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:
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:
# When a PR is merged into the develop branch it will be assigned a unique
# group identifier, so execution will continue even if another PR is merged
# while it is still running. In all other cases the group identifier is shared
# per branch, so that any in-progress runs are cancelled when a new commit is
# pushed.
group: ${{ github.workflow }}-${{ github.event_name == 'push' && github.ref == 'refs/heads/develop' && github.sha || github.ref }}
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
defaults:
@@ -65,16 +71,15 @@ defaults:
jobs:
check-missing-commits:
if: ${{ github.event_name == 'push' && github.ref_type == 'branch' && contains(fromJSON('["develop", "release"]'), github.ref_name) }}
uses: ./.github/workflows/reusable-check-missing-commits.yml
uses: ./.github/workflows/check-missing-commits.yml
build-test:
uses: ./.github/workflows/reusable-build-test.yml
uses: ./.github/workflows/build-test.yml
strategy:
fail-fast: ${{ github.event_name == 'merge_group' }}
matrix:
os: [linux, macos, windows]
with:
os: ${{ matrix.os }}
strategy_matrix: ${{ github.event_name == 'schedule' && 'all' || 'minimal' }}
strategy_matrix: "minimal"
secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
codecov_token: ${{ secrets.CODECOV_TOKEN }}

View File

@@ -7,9 +7,8 @@ on:
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
uses: XRPLF/actions/.github/workflows/pre-commit.yml@af1b0f0d764cda2e5435f5ac97b240d4bd4d95d3
with:
runs_on: ubuntu-latest
container: '{ "image": "ghcr.io/xrplf/ci/tools-rippled-pre-commit:sha-a8c7be1" }'
container: '{ "image": "ghcr.io/xrplf/ci/tools-rippled-pre-commit" }'

View File

@@ -23,24 +23,16 @@ defaults:
env:
BUILD_DIR: .build
NPROC_SUBTRACT: 2
jobs:
publish:
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:
- name: Checkout repository
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
- name: Get number of processors
uses: XRPLF/actions/.github/actions/get-nproc@046b1620f6bfd6cd0985dc82c3df02786801fe0a
id: nproc
with:
subtract: ${{ env.NPROC_SUBTRACT }}
- name: Check configuration
run: |
echo 'Checking path.'
@@ -54,16 +46,12 @@ jobs:
echo 'Checking Doxygen version.'
doxygen --version
- name: Build documentation
env:
BUILD_NPROC: ${{ steps.nproc.outputs.nproc }}
run: |
mkdir -p "${BUILD_DIR}"
cd "${BUILD_DIR}"
mkdir -p ${{ env.BUILD_DIR }}
cd ${{ env.BUILD_DIR }}
cmake -Donly_docs=ON ..
cmake --build . --target docs --parallel ${BUILD_NPROC}
cmake --build . --target docs --parallel $(nproc)
- name: Publish documentation
if: ${{ github.ref_type == 'branch' && github.ref_name == github.event.repository.default_branch }}
uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0

View File

@@ -1,77 +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
jobs:
build:
uses: ./.github/workflows/reusable-build.yml
with:
build_dir: ${{ inputs.build_dir }}
build_type: ${{ inputs.build_type }}
cmake_args: ${{ inputs.cmake_args }}
cmake_target: ${{ inputs.cmake_target }}
runs_on: ${{ inputs.runs_on }}
image: ${{ inputs.image }}
config_name: ${{ inputs.config_name }}
nproc_subtract: ${{ inputs.nproc_subtract }}
secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
test:
needs: build
uses: ./.github/workflows/reusable-test.yml
with:
run_tests: ${{ !inputs.build_only }}
verify_voidstar: ${{ contains(inputs.cmake_args, '-Dvoidstar=ON') }}
runs_on: ${{ inputs.runs_on }}
image: ${{ inputs.image }}
config_name: ${{ inputs.config_name }}
nproc_subtract: ${{ inputs.nproc_subtract }}

View File

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

View File

@@ -1,154 +0,0 @@
name: Build rippled
on:
workflow_call:
inputs:
build_dir:
description: "The directory where to build."
required: true
type: string
build_type:
description: 'The build type to use ("Debug", "Release").'
required: true
type: string
cmake_args:
description: "Additional arguments to pass to CMake."
required: true
type: string
cmake_target:
description: "The CMake target to build."
required: true
type: string
runs_on:
description: Runner to run the job on as a JSON string
required: true
type: string
image:
description: "The image to run in (leave empty to run natively)"
required: true
type: string
config_name:
description: "The name of the configuration."
required: true
type: string
nproc_subtract:
description: "The number of processors to subtract when calculating parallelism."
required: true
type: number
secrets:
CODECOV_TOKEN:
description: "The Codecov token to use for uploading coverage reports."
required: true
defaults:
run:
shell: bash
jobs:
build:
name: Build ${{ inputs.config_name }}
runs-on: ${{ fromJSON(inputs.runs_on) }}
container: ${{ inputs.image != '' && inputs.image || null }}
timeout-minutes: 60
steps:
- name: Cleanup workspace
if: ${{ runner.os == 'macOS' }}
uses: XRPLF/actions/.github/actions/cleanup-workspace@3f044c7478548e3c32ff68980eeb36ece02b364e
- name: Checkout repository
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
- name: Prepare runner
uses: XRPLF/actions/.github/actions/prepare-runner@99685816bb60a95a66852f212f382580e180df3a
with:
disable_ccache: false
- name: Print build environment
uses: ./.github/actions/print-env
- name: Get number of processors
uses: XRPLF/actions/.github/actions/get-nproc@046b1620f6bfd6cd0985dc82c3df02786801fe0a
id: nproc
with:
subtract: ${{ inputs.nproc_subtract }}
- name: Setup Conan
uses: ./.github/actions/setup-conan
- name: Build dependencies
uses: ./.github/actions/build-deps
with:
build_dir: ${{ inputs.build_dir }}
build_nproc: ${{ steps.nproc.outputs.nproc }}
build_type: ${{ inputs.build_type }}
# Set the verbosity to "quiet" for Windows to avoid an excessive
# amount of logs. For other OSes, the "verbose" logs are more useful.
log_verbosity: ${{ runner.os == 'Windows' && 'quiet' || 'verbose' }}
- name: Configure CMake
shell: bash
working-directory: ${{ inputs.build_dir }}
env:
BUILD_TYPE: ${{ inputs.build_type }}
CMAKE_ARGS: ${{ inputs.cmake_args }}
run: |
cmake \
-G '${{ runner.os == 'Windows' && 'Visual Studio 17 2022' || 'Ninja' }}' \
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
${CMAKE_ARGS} \
..
- name: Build the binary
shell: bash
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: Put built binaries in one location
shell: bash
working-directory: ${{ inputs.build_dir }}
env:
BUILD_TYPE_DIR: ${{ runner.os == 'Windows' && inputs.build_type || '' }}
CMAKE_TARGET: ${{ inputs.cmake_target }}
run: |
mkdir -p ./binaries/doctest/
cp ./${BUILD_TYPE_DIR}/rippled* ./binaries/
if [ "${CMAKE_TARGET}" != 'coverage' ]; then
cp ./src/tests/libxrpl/${BUILD_TYPE_DIR}/xrpl.test.* ./binaries/doctest/
fi
- name: Upload rippled artifact
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
env:
BUILD_DIR: ${{ inputs.build_dir }}
with:
name: rippled-${{ inputs.config_name }}
path: ${{ env.BUILD_DIR }}/binaries/
retention-days: 3
if-no-files-found: error
- name: Upload coverage report
if: ${{ github.repository_owner == 'XRPLF' && inputs.cmake_target == 'coverage' }}
uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5.4.3
with:
disable_search: true
disable_telem: true
fail_ci_if_error: true
files: ${{ inputs.build_dir }}/coverage.xml
plugins: noop
token: ${{ secrets.CODECOV_TOKEN }}
verbose: true

View File

@@ -35,7 +35,4 @@ jobs:
- name: Generate strategy matrix
working-directory: .github/scripts/strategy-matrix
id: generate
env:
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}"
run: ./generate.py ${{ inputs.strategy_matrix == 'all' && '--all' || '' }} ${{ inputs.os != '' && format('--config={0}.json', inputs.os) || '' }} >> "${GITHUB_OUTPUT}"

View File

@@ -1,111 +0,0 @@
name: Test rippled
on:
workflow_call:
inputs:
verify_voidstar:
description: "Whether to verify the presence of voidstar instrumentation."
required: true
type: boolean
run_tests:
description: "Whether to run unit tests"
required: true
type: boolean
runs_on:
description: Runner to run the job on as a JSON string
required: true
type: string
image:
description: "The image to run in (leave empty to run natively)"
required: true
type: string
config_name:
description: "The name of the configuration."
required: true
type: string
nproc_subtract:
description: "The number of processors to subtract when calculating parallelism."
required: true
type: number
jobs:
test:
name: Test ${{ inputs.config_name }}
runs-on: ${{ fromJSON(inputs.runs_on) }}
container: ${{ inputs.image != '' && inputs.image || null }}
timeout-minutes: 30
steps:
- name: Cleanup workspace
if: ${{ runner.os == 'macOS' }}
uses: XRPLF/actions/.github/actions/cleanup-workspace@3f044c7478548e3c32ff68980eeb36ece02b364e
- name: Get number of processors
uses: XRPLF/actions/.github/actions/get-nproc@046b1620f6bfd6cd0985dc82c3df02786801fe0a
id: nproc
with:
subtract: ${{ inputs.nproc_subtract }}
- name: Download rippled artifact
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: rippled-${{ inputs.config_name }}
- name: Make binary executable (Linux and macOS)
shell: bash
if: ${{ runner.os == 'Linux' || runner.os == 'macOS' }}
run: |
chmod +x ./rippled
- name: Check linking (Linux)
if: ${{ runner.os == 'Linux' }}
shell: bash
run: |
ldd ./rippled
if [ "$(ldd ./rippled | grep -E '(libstdc\+\+|libgcc)' | wc -l)" -eq 0 ]; then
echo 'The binary is statically linked.'
else
echo 'The binary is dynamically linked.'
exit 1
fi
- name: Verifying presence of instrumentation
if: ${{ inputs.verify_voidstar }}
shell: bash
run: |
./rippled --version | grep libvoidstar
- name: Run the embedded tests
if: ${{ inputs.run_tests }}
shell: bash
env:
BUILD_NPROC: ${{ steps.nproc.outputs.nproc }}
run: |
./rippled --unittest --unittest-jobs ${BUILD_NPROC}
- name: Run the separate tests
if: ${{ inputs.run_tests }}
env:
EXT: ${{ runner.os == 'Windows' && '.exe' || '' }}
shell: bash
run: |
for test_file in ./doctest/*${EXT}; do
echo "Executing $test_file"
chmod +x "$test_file"
if [[ "${{ runner.os }}" == "Windows" && "$test_file" == "./doctest/xrpl.test.net.exe" ]]; then
echo "Skipping $test_file on Windows"
else
"$test_file"
fi
done
- name: Debug failure (Linux)
if: ${{ failure() && runner.os == 'Linux' && inputs.run_tests }}
shell: bash
run: |
echo "IPv4 local port range:"
cat /proc/sys/net/ipv4/ip_local_port_range
echo "Netstat:"
netstat -an

View File

@@ -24,30 +24,26 @@ on:
branches: [develop]
paths:
- .github/workflows/upload-conan-deps.yml
- .github/workflows/reusable-strategy-matrix.yml
- .github/actions/build-deps/action.yml
- .github/actions/setup-conan/action.yml
- ".github/scripts/strategy-matrix/**"
- conanfile.py
- conan.lock
env:
CONAN_REMOTE_NAME: xrplf
CONAN_REMOTE_URL: https://conan.ripplex.io
NPROC_SUBTRACT: 2
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
# Generate the strategy matrix to be used by the following job.
generate-matrix:
uses: ./.github/workflows/reusable-strategy-matrix.yml
with:
strategy_matrix: ${{ github.event_name == 'pull_request' && 'minimal' || 'all' }}
# Build and upload the dependencies for each configuration.
run-upload-conan-deps:
needs:
- generate-matrix
@@ -56,52 +52,33 @@ jobs:
matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}
max-parallel: 10
runs-on: ${{ matrix.architecture.runner }}
container: ${{ contains(matrix.architecture.platform, 'linux') && format('ghcr.io/xrplf/ci/{0}-{1}:{2}-{3}-sha-{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:
- 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
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
- name: Prepare runner
uses: XRPLF/actions/.github/actions/prepare-runner@99685816bb60a95a66852f212f382580e180df3a
uses: XRPLF/actions/.github/actions/prepare-runner@638e0dc11ea230f91bd26622fb542116bb5254d5
with:
disable_ccache: false
- name: Print build environment
uses: ./.github/actions/print-env
- name: Get number of processors
uses: XRPLF/actions/.github/actions/get-nproc@046b1620f6bfd6cd0985dc82c3df02786801fe0a
id: nproc
with:
subtract: ${{ env.NPROC_SUBTRACT }}
- name: Setup Conan
uses: ./.github/actions/setup-conan
with:
conan_remote_name: ${{ env.CONAN_REMOTE_NAME }}
conan_remote_url: ${{ env.CONAN_REMOTE_URL }}
- name: Build dependencies
uses: ./.github/actions/build-deps
with:
build_dir: .build
build_nproc: ${{ steps.nproc.outputs.nproc }}
build_type: ${{ matrix.build_type }}
force_build: ${{ github.event_name == 'schedule' || github.event.inputs.force_source_build == 'true' }}
# Set the verbosity to "quiet" for Windows to avoid an excessive
# amount of logs. For other OSes, the "verbose" logs are more useful.
log_verbosity: ${{ runner.os == 'Windows' && 'quiet' || 'verbose' }}
- name: Log into Conan remote
if: ${{ github.repository_owner == 'XRPLF' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') }}
run: conan remote login "${CONAN_REMOTE_NAME}" "${{ secrets.CONAN_REMOTE_USERNAME }}" --password "${{ secrets.CONAN_REMOTE_PASSWORD }}"
- name: Login to Conan
if: github.repository_owner == 'XRPLF' && github.event_name != 'pull_request'
run: conan remote login -p ${{ secrets.CONAN_PASSWORD }} ${{ inputs.conan_remote_name }} ${{ secrets.CONAN_USERNAME }}
- name: Upload Conan packages
if: ${{ github.repository_owner == 'XRPLF' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') }}
env:
FORCE_OPTION: ${{ github.event.inputs.force_upload == 'true' && '--force' || '' }}
run: conan upload "*" --remote="${CONAN_REMOTE_NAME}" --confirm ${FORCE_OPTION}
if: github.repository_owner == 'XRPLF' && github.event_name != 'pull_request' && github.event_name != 'schedule'
run: conan upload "*" -r=${{ inputs.conan_remote_name }} --confirm ${{ github.event.inputs.force_upload == 'true' && '--force' || '' }}

3
.gitignore vendored
View File

@@ -111,3 +111,6 @@ bld.rippled/
# Suggested in-tree build directory
/.build*/
# Rust
external/*/target

View File

@@ -39,12 +39,17 @@ found here](./docs/build/environment.md).
- [Python 3.11](https://www.python.org/downloads/), or higher
- [Conan 2.17](https://conan.io/downloads.html)[^1], or higher
- [CMake 3.22](https://cmake.org/download/), or higher
- [CMake 3.22](https://cmake.org/download/)[^2], or higher
[^1]:
It is possible to build with Conan 1.60+, but the instructions are
significantly different, which is why we are not recommending it.
[^2]:
CMake 4 is not yet supported by all dependencies required by this project.
If you are affected by this issue, follow [conan workaround for cmake
4](#workaround-for-cmake-4)
`rippled` is written in the C++20 dialect and includes the `<concepts>` header.
The [minimum compiler versions][2] required are:
@@ -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
```
#### Workaround for CMake 4
If your system CMake is version 4 rather than 3, you may have to configure Conan
profile to use CMake version 3 for dependencies, by adding the following two
lines to your profile:
```text
[tool_requires]
!cmake/*: cmake/[>=3 <4]
```
This will force Conan to download and use a locally cached CMake 3 version, and
is needed because some of the dependencies used by this project do not support
CMake 4.
#### Clang workaround for grpc
If your compiler is clang, version 19 or later, or apple-clang, version 17 or

View File

@@ -96,6 +96,7 @@ set(SECP256K1_BUILD_EXHAUSTIVE_TESTS FALSE)
set(SECP256K1_BUILD_CTIME_TESTS FALSE)
set(SECP256K1_BUILD_EXAMPLES FALSE)
add_subdirectory(external/secp256k1)
add_subdirectory(external/rust-test)
add_library(secp256k1::secp256k1 ALIAS secp256k1)
add_subdirectory(external/ed25519-donna)
add_subdirectory(external/antithesis-sdk)
@@ -129,6 +130,7 @@ target_link_libraries(ripple_libs INTERFACE
secp256k1::secp256k1
soci::soci
SQLite::SQLite3
RustTest
)
# Work around changes to Conan recipe for now.

View File

@@ -975,47 +975,6 @@
# number of ledger records online. Must be greater
# than or equal to ledger_history.
#
# Optional keys for NuDB only:
#
# nudb_block_size EXPERIMENTAL: Block size in bytes for NuDB storage.
# Must be a power of 2 between 4096 and 32768. Default is 4096.
#
# This parameter controls the fundamental storage unit
# size for NuDB's internal data structures. The choice
# of block size can significantly impact performance
# depending on your storage hardware and filesystem:
#
# - 4096 bytes: Optimal for most standard SSDs and
# traditional filesystems (ext4, NTFS, HFS+).
# Provides good balance of performance and storage
# efficiency. Recommended for most deployments.
# Minimizes memory footprint and provides consistent
# low-latency access patterns across diverse hardware.
#
# - 8192-16384 bytes: May improve performance on
# high-end NVMe SSDs and copy-on-write filesystems
# like ZFS or Btrfs that benefit from larger block
# alignment. Can reduce metadata overhead for large
# databases. Offers better sequential throughput and
# reduced I/O operations at the cost of higher memory
# usage per operation.
#
# - 32768 bytes (32K): Maximum supported block size
# for high-performance scenarios with very fast
# storage. May increase memory usage and reduce
# efficiency for smaller databases. Best suited for
# enterprise environments with abundant RAM.
#
# Performance testing is recommended before deploying
# any non-default block size in production environments.
#
# Note: This setting cannot be changed after database
# creation without rebuilding the entire database.
# Choose carefully based on your hardware and expected
# database size.
#
# Example: nudb_block_size=4096
#
# These keys modify the behavior of online_delete, and thus are only
# relevant if online_delete is defined and non-zero:
#
@@ -1512,7 +1471,6 @@ secure_gateway = 127.0.0.1
[node_db]
type=NuDB
path=/var/lib/rippled/db/nudb
nudb_block_size=4096
online_delete=512
advisory_delete=0

View File

@@ -104,11 +104,6 @@
# 2025-08-28, Bronek Kozicki
# - 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
#
# USAGE:
#
# 1. Copy this file into your cmake modules path.
@@ -117,8 +112,10 @@
# using a CMake option() to enable it just optionally):
# include(CodeCoverage)
#
# 3. Append necessary compiler flags and linker flags for all supported source files:
# add_code_coverage_to_target(<target> <PRIVATE|PUBLIC|INTERFACE>)
# 3. Append necessary compiler flags for all supported source files:
# 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
#
@@ -207,69 +204,67 @@ endforeach()
set(COVERAGE_COMPILER_FLAGS "-g --coverage"
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)")
include(CheckCXXCompilerFlag)
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)
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()
check_c_compiler_flag(-fprofile-abs-path HAVE_c_fprofile_abs_path)
if(HAVE_c_fprofile_abs_path)
set(COVERAGE_C_COMPILER_FLAGS "${COVERAGE_C_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")
set(COVERAGE_C_COMPILER_FLAGS "${COVERAGE_COMPILER_FLAGS} -fprofile-abs-path")
endif()
check_cxx_compiler_flag(-fprofile-update=atomic 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()
check_c_compiler_flag(-fprofile-update=atomic 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()
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()
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)
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")
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
# Builds dependencies, runs the given executable and outputs reports.
# NOTE! The executable should always have a ZERO as exit code otherwise
@@ -459,19 +454,18 @@ function(setup_target_for_coverage_gcovr)
)
endfunction() # setup_target_for_coverage_gcovr
function(add_code_coverage_to_target name scope)
separate_arguments(COVERAGE_CXX_COMPILER_FLAGS NATIVE_COMMAND "${COVERAGE_CXX_COMPILER_FLAGS}")
separate_arguments(COVERAGE_C_COMPILER_FLAGS NATIVE_COMMAND "${COVERAGE_C_COMPILER_FLAGS}")
separate_arguments(COVERAGE_CXX_LINKER_FLAGS NATIVE_COMMAND "${COVERAGE_CXX_LINKER_FLAGS}")
separate_arguments(COVERAGE_C_LINKER_FLAGS NATIVE_COMMAND "${COVERAGE_C_LINKER_FLAGS}")
function(append_coverage_compiler_flags)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
message(STATUS "Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}")
endfunction() # append_coverage_compiler_flags
# Add compiler options to the target
target_compile_options(${name} ${scope}
$<$<COMPILE_LANGUAGE:CXX>:${COVERAGE_CXX_COMPILER_FLAGS}>
$<$<COMPILE_LANGUAGE:C>:${COVERAGE_C_COMPILER_FLAGS}>)
target_link_libraries (${name} ${scope}
$<$<LINK_LANGUAGE:CXX>:${COVERAGE_CXX_LINKER_FLAGS} gcov>
$<$<LINK_LANGUAGE:C>:${COVERAGE_C_LINKER_FLAGS} gcov>
)
endfunction() # add_code_coverage_to_target
# Setup coverage for specific library
function(append_coverage_compiler_flags_to_target name)
separate_arguments(_flag_list NATIVE_COMMAND "${COVERAGE_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} PRIVATE gcov)
endif()
endfunction()

View File

@@ -45,7 +45,7 @@ if (static OR APPLE OR MSVC)
set (OPENSSL_USE_STATIC_LIBS ON)
endif ()
set (OPENSSL_MSVC_STATIC_RT ON)
find_dependency (OpenSSL REQUIRED)
find_dependency (OpenSSL 1.1.1 REQUIRED)
find_dependency (ZLIB)
find_dependency (date)
if (TARGET ZLIB::ZLIB)

View File

@@ -53,15 +53,14 @@ add_library(xrpl.imports.main INTERFACE)
target_link_libraries(xrpl.imports.main
INTERFACE
absl::random_random
date::date
ed25519::ed25519
LibArchive::LibArchive
OpenSSL::Crypto
Ripple::boost
Ripple::libs
Ripple::opts
Ripple::syslibs
absl::random_random
date::date
ed25519::ed25519
secp256k1::secp256k1
xrpl.libpb
xxHash::xxhash
@@ -112,27 +111,6 @@ target_link_libraries(xrpl.libxrpl.net PUBLIC
add_module(xrpl server)
target_link_libraries(xrpl.libxrpl.server PUBLIC xrpl.libxrpl.protocol)
add_module(xrpl nodestore)
target_link_libraries(xrpl.libxrpl.nodestore PUBLIC
xrpl.libxrpl.basics
xrpl.libxrpl.json
xrpl.libxrpl.protocol
)
add_module(xrpl shamap)
target_link_libraries(xrpl.libxrpl.shamap PUBLIC
xrpl.libxrpl.basics
xrpl.libxrpl.crypto
xrpl.libxrpl.protocol
xrpl.libxrpl.nodestore
)
add_module(xrpl ledger)
target_link_libraries(xrpl.libxrpl.ledger PUBLIC
xrpl.libxrpl.basics
xrpl.libxrpl.json
xrpl.libxrpl.protocol
)
add_library(xrpl.libxrpl)
set_target_properties(xrpl.libxrpl PROPERTIES OUTPUT_NAME xrpl)
@@ -152,10 +130,7 @@ target_link_modules(xrpl PUBLIC
protocol
resource
server
nodestore
shamap
net
ledger
)
# All headers in libxrpl are in modules.

View File

@@ -33,8 +33,6 @@ setup_target_for_coverage_gcovr(
FORMAT ${coverage_format}
EXECUTABLE rippled
EXECUTABLE_ARGS --unittest$<$<BOOL:${coverage_test}>:=${coverage_test}> --unittest-jobs ${coverage_test_parallelism} --quiet --unittest-log
EXCLUDE "src/test" "src/tests" "include/xrpl/beast/test" "include/xrpl/beast/unit_test" "${CMAKE_BINARY_DIR}/pb-xrpl.libpb"
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)

View File

@@ -8,23 +8,19 @@ install (
TARGETS
common
opts
ripple_boost
ripple_libs
ripple_syslibs
ripple_boost
xrpl.imports.main
xrpl.libpb
xrpl.libxrpl
xrpl.libxrpl.basics
xrpl.libxrpl.beast
xrpl.libxrpl.crypto
xrpl.libxrpl.json
xrpl.libxrpl.ledger
xrpl.libxrpl.net
xrpl.libxrpl.nodestore
xrpl.libxrpl.protocol
xrpl.libxrpl.resource
xrpl.libxrpl.server
xrpl.libxrpl.shamap
xrpl.libxrpl.net
xrpl.libxrpl
antithesis-sdk-cpp
EXPORT RippleExports
LIBRARY DESTINATION lib
@@ -41,7 +37,7 @@ install(CODE "
set(CMAKE_MODULE_PATH \"${CMAKE_MODULE_PATH}\")
include(create_symbolic_link)
create_symbolic_link(xrpl \
\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/ripple)
\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/ripple)
")
install (EXPORT RippleExports
@@ -75,7 +71,7 @@ if (is_root_project AND TARGET rippled)
set(CMAKE_MODULE_PATH \"${CMAKE_MODULE_PATH}\")
include(create_symbolic_link)
create_symbolic_link(rippled${suffix} \
\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}/xrpld${suffix})
\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}/xrpld${suffix})
")
endif ()

View File

@@ -28,11 +28,15 @@ target_compile_options (opts
$<$<AND:$<BOOL:${is_gcc}>,$<COMPILE_LANGUAGE:CXX>>:-Wsuggest-override>
$<$<BOOL:${is_gcc}>:-Wno-maybe-uninitialized>
$<$<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>
$<$<AND:$<BOOL:${is_gcc}>,$<BOOL:${profile}>>:-p>)
target_link_libraries (opts
INTERFACE
$<$<AND:$<BOOL:${is_gcc}>,$<BOOL:${coverage}>>:-g --coverage -fprofile-abs-path>
$<$<AND:$<BOOL:${is_clang}>,$<BOOL:${coverage}>>:-g --coverage>
$<$<BOOL:${profile}>:-pg>
$<$<AND:$<BOOL:${is_gcc}>,$<BOOL:${profile}>>:-p>)

View File

@@ -1,4 +1,4 @@
option (validator_keys "Enables building of validator-keys tool as a separate target (imported via FetchContent)" OFF)
option (validator_keys "Enables building of validator-keys-tool as a separate target (imported via FetchContent)" OFF)
if (validator_keys)
git_branch (current_branch)
@@ -6,15 +6,17 @@ if (validator_keys)
if (NOT (current_branch STREQUAL "release"))
set (current_branch "master")
endif ()
message (STATUS "Tracking ValidatorKeys branch: ${current_branch}")
message (STATUS "tracking ValidatorKeys branch: ${current_branch}")
FetchContent_Declare (
validator_keys
validator_keys_src
GIT_REPOSITORY https://github.com/ripple/validator-keys-tool.git
GIT_TAG "${current_branch}"
)
FetchContent_MakeAvailable(validator_keys)
set_target_properties(validator-keys PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
install(TARGETS validator-keys RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
FetchContent_GetProperties (validator_keys_src)
if (NOT validator_keys_src_POPULATED)
message (STATUS "Pausing to download ValidatorKeys...")
FetchContent_Populate (validator_keys_src)
endif ()
add_subdirectory (${validator_keys_src_SOURCE_DIR} ${CMAKE_BINARY_DIR}/validator-keys)
endif ()

View File

@@ -7,7 +7,7 @@ function(xrpl_add_test name)
"${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(
${target}

View File

@@ -9,7 +9,7 @@
"rocksdb/10.0.1#85537f46e538974d67da0c3977de48ac%1756234304.347",
"re2/20230301#dfd6e2bf050eb90ddd8729cfb4c844a4%1756234257.976",
"protobuf/3.21.12#d927114e28de9f4691a6bbcdd9a529d1%1756234251.614",
"openssl/3.5.4#a1d5835cc6ed5c5b8f3cd5b9b5d24205%1759746684.671",
"openssl/3.5.2#0c5a5e15ae569f45dff57adcf1770cf7%1756234259.61",
"nudb/2.0.9#c62cfd501e57055a7e0d8ee3d5e5427d%1756234237.107",
"lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1756234228.999",
"libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1756223727.64",

View File

@@ -1,5 +1,9 @@
# 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.download:parallel={{ os.cpu_count() }}
core.upload:parallel={{ os.cpu_count() }}
tools.build:jobs={{ (os.cpu_count() * 4/5) | int }}
tools.build:verbosity=verbose
tools.compilation:verbosity=verbose

View File

@@ -21,11 +21,14 @@ compiler.libcxx={{detect_api.detect_libcxx(compiler, version, compiler_exe)}}
[conf]
{% 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 %}
{% 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 == "gcc" and compiler_version < 13 %}
tools.build:cxxflags+=['-Wno-restrict']
tools.build:cxxflags=['-Wno-restrict']
{% endif %}
[tool_requires]
!cmake/*: cmake/[>=3 <4]

View File

@@ -27,7 +27,7 @@ class Xrpl(ConanFile):
'grpc/1.50.1',
'libarchive/3.8.1',
'nudb/2.0.9',
'openssl/3.5.4',
'openssl/3.5.2',
'soci/4.0.3',
'zlib/1.3.1',
]

15
external/rust-test/CMakeLists.txt vendored Normal file
View File

@@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 3.15)
project(RustTest)
set(CMAKE_INSTALL_CMAKEDIR "lib/cmake/RustTest")
execute_process(COMMAND cargo run --bin install -- --release WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
set(INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/target/install/release/include/")
add_library(RustTest STATIC IMPORTED GLOBAL)
set_target_properties(RustTest PROPERTIES
IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/target/install/release/lib/RustTest.a"
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/target/install/release/include/"
)

568
external/rust-test/Cargo.lock generated vendored Normal file
View File

@@ -0,0 +1,568 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "RustTest"
version = "0.1.0"
dependencies = [
"cbindgen",
]
[[package]]
name = "anstream"
version = "0.6.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd"
[[package]]
name = "anstyle-parse"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9"
dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882"
dependencies = [
"anstyle",
"once_cell_polyfill",
"windows-sys 0.59.0",
]
[[package]]
name = "bitflags"
version = "2.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
[[package]]
name = "cbindgen"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "975982cdb7ad6a142be15bdf84aea7ec6a9e5d4d797c004d43185b24cfe4e684"
dependencies = [
"clap",
"heck",
"indexmap",
"log",
"proc-macro2",
"quote",
"serde",
"serde_json",
"syn",
"tempfile",
"toml",
]
[[package]]
name = "cfg-if"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
[[package]]
name = "clap"
version = "4.5.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be92d32e80243a54711e5d7ce823c35c41c9d929dc4ab58e1276f625841aadf9"
dependencies = [
"clap_builder",
]
[[package]]
name = "clap_builder"
version = "4.5.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "707eab41e9622f9139419d573eca0900137718000c517d47da73045f54331c3d"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_lex"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675"
[[package]]
name = "colorchoice"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
[[package]]
name = "equivalent"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "errno"
version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad"
dependencies = [
"libc",
"windows-sys 0.60.2",
]
[[package]]
name = "fastrand"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
[[package]]
name = "getrandom"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
dependencies = [
"cfg-if",
"libc",
"r-efi",
"wasi",
]
[[package]]
name = "hashbrown"
version = "0.15.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5"
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "indexmap"
version = "2.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661"
dependencies = [
"equivalent",
"hashbrown",
]
[[package]]
name = "is_terminal_polyfill"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "itoa"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]]
name = "libc"
version = "0.2.174"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
[[package]]
name = "linux-raw-sys"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12"
[[package]]
name = "log"
version = "0.4.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
[[package]]
name = "memchr"
version = "2.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
[[package]]
name = "once_cell"
version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "once_cell_polyfill"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
[[package]]
name = "proc-macro2"
version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
dependencies = [
"proc-macro2",
]
[[package]]
name = "r-efi"
version = "5.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
[[package]]
name = "rustix"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8"
dependencies = [
"bitflags",
"errno",
"libc",
"linux-raw-sys",
"windows-sys 0.60.2",
]
[[package]]
name = "ryu"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
[[package]]
name = "serde"
version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.141"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3"
dependencies = [
"itoa",
"memchr",
"ryu",
"serde",
]
[[package]]
name = "serde_spanned"
version = "0.6.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3"
dependencies = [
"serde",
]
[[package]]
name = "strsim"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
version = "2.0.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tempfile"
version = "3.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1"
dependencies = [
"fastrand",
"getrandom",
"once_cell",
"rustix",
"windows-sys 0.59.0",
]
[[package]]
name = "toml"
version = "0.8.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362"
dependencies = [
"serde",
"serde_spanned",
"toml_datetime",
"toml_edit",
]
[[package]]
name = "toml_datetime"
version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
dependencies = [
"serde",
]
[[package]]
name = "toml_edit"
version = "0.22.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
dependencies = [
"indexmap",
"serde",
"serde_spanned",
"toml_datetime",
"toml_write",
"winnow",
]
[[package]]
name = "toml_write"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
[[package]]
name = "unicode-ident"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
name = "utf8parse"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "wasi"
version = "0.14.2+wasi-0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3"
dependencies = [
"wit-bindgen-rt",
]
[[package]]
name = "windows-sys"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-sys"
version = "0.60.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
dependencies = [
"windows-targets 0.53.2",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm 0.52.6",
"windows_aarch64_msvc 0.52.6",
"windows_i686_gnu 0.52.6",
"windows_i686_gnullvm 0.52.6",
"windows_i686_msvc 0.52.6",
"windows_x86_64_gnu 0.52.6",
"windows_x86_64_gnullvm 0.52.6",
"windows_x86_64_msvc 0.52.6",
]
[[package]]
name = "windows-targets"
version = "0.53.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef"
dependencies = [
"windows_aarch64_gnullvm 0.53.0",
"windows_aarch64_msvc 0.53.0",
"windows_i686_gnu 0.53.0",
"windows_i686_gnullvm 0.53.0",
"windows_i686_msvc 0.53.0",
"windows_x86_64_gnu 0.53.0",
"windows_x86_64_gnullvm 0.53.0",
"windows_x86_64_msvc 0.53.0",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_aarch64_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnu"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_i686_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnu"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "windows_x86_64_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
[[package]]
name = "winnow"
version = "0.7.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95"
dependencies = [
"memchr",
]
[[package]]
name = "wit-bindgen-rt"
version = "0.39.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
dependencies = [
"bitflags",
]

13
external/rust-test/Cargo.toml vendored Normal file
View File

@@ -0,0 +1,13 @@
[package]
name = "RustTest"
version = "0.1.0"
edition = "2024"
[lib]
name = "test"
crate-type = ["staticlib"]
[build-dependencies]
cbindgen = "0.29"
[dependencies]

15
external/rust-test/build.rs vendored Normal file
View File

@@ -0,0 +1,15 @@
use std::{env};
use std::{path::PathBuf};
fn main() {
let crate_name = env::var("CARGO_PKG_NAME").unwrap();
let header_name = format!("{}.h", crate_name);
let crate_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
let header_path = out_dir.join(header_name);
cbindgen::generate(&crate_dir)
.expect("Unable to generate bindings")
.write_to_file(header_path);
}

54
external/rust-test/src/bin/install.rs vendored Normal file
View File

@@ -0,0 +1,54 @@
use std::path::PathBuf;
use std::process::{Command};
use std::{env, fs};
fn main() {
let args: Vec<String> = env::args().collect();
// Pass 'build' for the first argument and pass all other
// parameters to the cargo command
Command::new("cargo")
.arg("build")
.args(args.iter().skip(1))
.status()
.expect("failed to run cargo");
// Determine the build config
let build_config = args.iter()
.map(|arg| arg.to_lowercase())
.filter(|arg| arg == "--release" || arg == "--debug")
.next()
.unwrap_or("--debug".to_string());
let config = if build_config == "--debug" { "debug" } else { "release" };
let crate_name = env::var("CARGO_PKG_NAME").unwrap();
let lib_name = format!("{}.a", crate_name);
let header_name = format!("{}.h", crate_name);
let crate_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
let header_out_path = out_dir.join(&header_name);
let binary_dir = crate_dir.join(format!("target/{config}"));
let lib_path = fs::read_dir(binary_dir)
.expect("Failed to find lib files")
.filter_map(Result::ok)
.map(|entry| entry.path())
.find(|path| path.extension().and_then(|s| s.to_str()) == Some("a"))
.expect("Can't find a lib file");
let install_base_dir = crate_dir.join("target").join("install").join(config);
let lib_install_dir = install_base_dir.join("lib");
let include_install_dir = install_base_dir.join("include");
let include_install_path = include_install_dir.join(&header_name);
let lib_install_path = lib_install_dir.join(&lib_name);
let _ = std::fs::create_dir_all(&lib_install_dir);
let _ = std::fs::create_dir_all(&include_install_dir);
fs::copy(header_out_path, &include_install_path).expect("Failed to install the header file");
fs::copy(lib_path, &lib_install_path)
.expect("Failed to install the lib file");
println!("Installed to {}", install_base_dir.display());
}

4
external/rust-test/src/lib.rs vendored Normal file
View File

@@ -0,0 +1,4 @@
#[unsafe(no_mangle)]
pub extern "C" fn add(a: i32, b: i32) -> i32 {
a + b
}

View File

@@ -654,14 +654,12 @@ SharedWeakUnion<T>::convertToWeak()
break;
case destroy:
// We just added a weak ref. How could we destroy?
// LCOV_EXCL_START
UNREACHABLE(
"ripple::SharedWeakUnion::convertToWeak : destroying freshly "
"added ref");
delete p;
unsafeSetRawPtr(nullptr);
return true; // Should never happen
// LCOV_EXCL_STOP
case partialDestroy:
// This is a weird case. We just converted the last strong
// pointer to a weak pointer.

View File

@@ -632,16 +632,6 @@ to_string(base_uint<Bits, Tag> const& a)
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>
inline std::ostream&
operator<<(std::ostream& out, base_uint<Bits, Tag> const& u)

View File

@@ -28,8 +28,9 @@ namespace ripple {
// the destination can hold all values of the source. This is particularly
// handy when the source or destination is an enumeration type.
template <class Src, class Dest>
concept SafeToCast = (std::is_integral_v<Src> && std::is_integral_v<Dest>) &&
template <class Dest, class Src>
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_signed<Dest>::value
? sizeof(Dest) > sizeof(Src)
@@ -77,7 +78,7 @@ inline constexpr std::
unsafe_cast(Src s) noexcept
{
static_assert(
!SafeToCast<Src, Dest>,
!is_safetocasttovalue_v<Dest, Src>,
"Only unsafe if casting signed to unsigned or "
"destination is too small");
return static_cast<Dest>(s);

View File

@@ -94,11 +94,7 @@ hash_append(Hasher& h, beast::IP::Address const& addr) noexcept
else if (addr.is_v6())
hash_append(h, addr.to_v6().to_bytes());
else
{
// LCOV_EXCL_START
UNREACHABLE("beast::hash_append : invalid address type");
// LCOV_EXCL_STOP
}
}
} // namespace beast

View File

@@ -39,16 +39,11 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#endif
#define XRPL_ASSERT ALWAYS_OR_UNREACHABLE
#define XRPL_ASSERT_PARTS(cond, function, description, ...) \
XRPL_ASSERT(cond, function " : " description)
// How to use the instrumentation macros:
//
// * XRPL_ASSERT if cond must be true but the line might not be reached during
// 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.
// Same like `assert` in normal use.
// * REACHABLE if the line must be reached during fuzzing

View File

@@ -46,7 +46,7 @@ public:
* without formatting (not human friendly).
*
* The JSON document is written in a single line. It is not intended for 'human'
* consumption, but may be useful to support feature such as RPC where bandwidth
* consumption, but may be useful to support feature such as RPC where bandwith
* is limited. \sa Reader, Value
*/

View File

@@ -20,11 +20,6 @@
#ifndef RIPPLE_PROTOCOL_APIVERSION_H_INCLUDED
#define RIPPLE_PROTOCOL_APIVERSION_H_INCLUDED
#include <xrpl/beast/core/SemanticVersion.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/json/json_value.h>
#include <xrpl/protocol/jss.h>
#include <type_traits>
#include <utility>
@@ -77,77 +72,6 @@ static_assert(apiMaximumSupportedVersion >= apiMinimumSupportedVersion);
static_assert(apiBetaVersion >= apiMaximumSupportedVersion);
static_assert(apiMaximumValidVersion >= apiMaximumSupportedVersion);
template <class JsonObject>
void
setVersion(JsonObject& parent, unsigned int apiVersion, bool betaEnabled)
{
XRPL_ASSERT(
apiVersion != apiInvalidVersion,
"ripple::RPC::setVersion : input is valid");
auto& retObj = addObject(parent, jss::version);
if (apiVersion == apiVersionIfUnspecified)
{
// API version numbers used in API version 1
static beast::SemanticVersion const firstVersion{"1.0.0"};
static beast::SemanticVersion const goodVersion{"1.0.0"};
static beast::SemanticVersion const lastVersion{"1.0.0"};
retObj[jss::first] = firstVersion.print();
retObj[jss::good] = goodVersion.print();
retObj[jss::last] = lastVersion.print();
}
else
{
retObj[jss::first] = apiMinimumSupportedVersion.value;
retObj[jss::last] =
betaEnabled ? apiBetaVersion : apiMaximumSupportedVersion;
}
}
/**
* Retrieve the api version number from the json value
*
* Note that APIInvalidVersion will be returned if
* 1) the version number field has a wrong format
* 2) the version number retrieved is out of the supported range
* 3) the version number is unspecified and
* APIVersionIfUnspecified is out of the supported range
*
* @param jv a Json value that may or may not specifies
* the api version number
* @param betaEnabled if the beta API version is enabled
* @return the api version number
*/
inline unsigned int
getAPIVersionNumber(Json::Value const& jv, bool betaEnabled)
{
static Json::Value const minVersion(RPC::apiMinimumSupportedVersion);
Json::Value const maxVersion(
betaEnabled ? RPC::apiBetaVersion : RPC::apiMaximumSupportedVersion);
if (jv.isObject())
{
if (jv.isMember(jss::api_version))
{
auto const specifiedVersion = jv[jss::api_version];
if (!specifiedVersion.isInt() && !specifiedVersion.isUInt())
{
return RPC::apiInvalidVersion;
}
auto const specifiedVersionInt = specifiedVersion.asInt();
if (specifiedVersionInt < minVersion ||
specifiedVersionInt > maxVersion)
{
return RPC::apiInvalidVersion;
}
return specifiedVersionInt;
}
}
return RPC::apiVersionIfUnspecified;
}
} // namespace RPC
template <unsigned minVer, unsigned maxVer, typename Fn, typename... Args>

View File

@@ -1,180 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2025 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_PROTOCOL_CONFIDENTIALTRANSFER_H_INCLUDED
#define RIPPLE_PROTOCOL_CONFIDENTIALTRANSFER_H_INCLUDED
#include <xrpl/basics/Slice.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/MPTIssue.h>
#include <xrpl/protocol/Protocol.h>
#include <xrpl/protocol/Rate.h>
#include <xrpl/protocol/STLedgerEntry.h>
#include <xrpl/protocol/STObject.h>
#include <xrpl/protocol/Serializer.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/detail/secp256k1.h>
#include <secp256k1.h>
namespace ripple {
/**
* @brief Generates a new secp256k1 key pair.
*/
SECP256K1_API int
secp256k1_elgamal_generate_keypair(
secp256k1_context const* ctx,
unsigned char* privkey,
secp256k1_pubkey* pubkey);
/**
* @brief Encrypts a 64-bit amount using ElGamal.
*/
SECP256K1_API int
secp256k1_elgamal_encrypt(
secp256k1_context const* ctx,
secp256k1_pubkey* c1,
secp256k1_pubkey* c2,
secp256k1_pubkey const* pubkey_Q,
uint64_t amount,
unsigned char const* blinding_factor);
/**
* @brief Decrypts an ElGamal ciphertext to recover the amount.
*/
SECP256K1_API int
secp256k1_elgamal_decrypt(
secp256k1_context const* ctx,
uint64_t* amount,
secp256k1_pubkey const* c1,
secp256k1_pubkey const* c2,
unsigned char const* privkey);
/**
* @brief Homomorphically adds two ElGamal ciphertexts.
*/
SECP256K1_API int
secp256k1_elgamal_add(
secp256k1_context const* ctx,
secp256k1_pubkey* sum_c1,
secp256k1_pubkey* sum_c2,
secp256k1_pubkey const* a_c1,
secp256k1_pubkey const* a_c2,
secp256k1_pubkey const* b_c1,
secp256k1_pubkey const* b_c2);
/**
* @brief Homomorphically subtracts two ElGamal ciphertexts.
*/
SECP256K1_API int
secp256k1_elgamal_subtract(
secp256k1_context const* ctx,
secp256k1_pubkey* diff_c1,
secp256k1_pubkey* diff_c2,
secp256k1_pubkey const* a_c1,
secp256k1_pubkey const* a_c2,
secp256k1_pubkey const* b_c1,
secp256k1_pubkey const* b_c2);
/**
* @brief Generates the canonical encrypted zero for a given MPT token instance.
*
* This ciphertext represents a zero balance for a specific account's holding
* of a token defined by its MPTokenIssuanceID.
*
* @param[in] ctx A pointer to a valid secp256k1 context.
* @param[out] enc_zero_c1 The C1 component of the canonical ciphertext.
* @param[out] enc_zero_c2 The C2 component of the canonical ciphertext.
* @param[in] pubkey The ElGamal public key of the account holder.
* @param[in] account_id A pointer to the 20-byte AccountID.
* @param[in] mpt_issuance_id A pointer to the 24-byte MPTokenIssuanceID.
*
* @return 1 on success, 0 on failure.
*/
SECP256K1_API int
generate_canonical_encrypted_zero(
secp256k1_context const* ctx,
secp256k1_pubkey* enc_zero_c1,
secp256k1_pubkey* enc_zero_c2,
secp256k1_pubkey const* pubkey,
unsigned char const* account_id, // 20 bytes
unsigned char const* mpt_issuance_id // 24 bytes
);
// breaks a 66-byte encrypted amount into two 33-byte components
// then parses each 33-byte component into 64-byte secp256k1_pubkey format
bool
makeEcPair(Slice const& buffer, secp256k1_pubkey& out1, secp256k1_pubkey& out2);
// serialize two secp256k1_pubkey components back into compressed 66-byte form
bool
serializeEcPair(
secp256k1_pubkey const& in1,
secp256k1_pubkey const& in2,
Buffer& buffer);
/**
* @brief Verifies that a buffer contains two valid, parsable EC public keys.
* @param buffer The input buffer containing two concatenated components.
* @return true if both components can be parsed successfully, false otherwise.
*/
bool
isValidCiphertext(Slice const& buffer);
TER
homomorphicAdd(Slice const& a, Slice const& b, Buffer& out);
TER
homomorphicSubtract(Slice const& a, Slice const& b, Buffer& out);
TER
proveEquality(
Slice const& proof,
Slice const& encAmt, // encrypted amount
Slice const& pubkey,
uint64_t const amount,
uint256 const& txHash, // Transaction context data
std::uint32_t const spendVersion);
Buffer
encryptAmount(uint64_t amt, Slice const& pubKeySlice);
Buffer
encryptCanonicalZeroAmount(
Slice const& pubKeySlice,
AccountID const& account,
MPTID const& mptId);
TER
verifyConfidentialSendProof(
Slice const& proof,
Slice const& encSenderBalance,
Slice const& encSenderAmt,
Slice const& encDestAmt,
Slice const& encIssuerAmt,
Slice const& senderPubKey,
Slice const& destPubKey,
Slice const& issuerPubKey,
std::uint32_t const version,
uint256 const& txHash);
} // namespace ripple
#endif

View 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

View File

@@ -287,11 +287,9 @@ delegate(AccountID const& account, AccountID const& authorizedAccount) noexcept;
Keylet
bridge(STXChainBridge const& bridge, STXChainBridge::ChainType chainType);
// `seq` is stored as `sfXChainClaimID` in the object
Keylet
xChainClaimID(STXChainBridge const& bridge, std::uint64_t seq);
// `seq` is stored as `sfXChainAccountCreateCount` in the object
Keylet
xChainCreateAccountClaimID(STXChainBridge const& bridge, std::uint64_t seq);

View File

@@ -56,7 +56,7 @@ enum LedgerEntryType : std::uint16_t
#pragma push_macro("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>
@@ -187,16 +187,6 @@ enum LedgerSpecificFlags {
lsfMPTCanTrade = 0x00000010,
lsfMPTCanTransfer = 0x00000020,
lsfMPTCanClawback = 0x00000040,
lsfMPTNoConfidentialTransfer = 0x00000080,
lsmfMPTCanMutateCanLock = 0x00000002,
lsmfMPTCanMutateRequireAuth = 0x00000004,
lsmfMPTCanMutateCanEscrow = 0x00000008,
lsmfMPTCanMutateCanTrade = 0x00000010,
lsmfMPTCanMutateCanTransfer = 0x00000020,
lsmfMPTCanMutateCanClawback = 0x00000040,
lsmfMPTCanMutateMetadata = 0x00010000,
lsmfMPTCanMutateTransferFee = 0x00020000,
// ltMPTOKEN
lsfMPTAuthorized = 0x00000002,

View File

@@ -74,9 +74,6 @@ public:
Permission&
operator=(Permission const&) = delete;
std::optional<std::string>
getPermissionName(std::uint32_t const value) const;
std::optional<std::uint32_t>
getGranularValue(std::string const& name) const;
@@ -86,9 +83,6 @@ public:
std::optional<TxType>
getGranularTxType(GranularPermissionType const& gpType) const;
std::optional<std::reference_wrapper<uint256 const>> const
getTxFeature(TxType txType) const;
bool
isDelegatable(std::uint32_t const& permissionValue, Rules const& rules)
const;

View File

@@ -22,6 +22,7 @@
#include <xrpl/basics/ByteUtilities.h>
#include <xrpl/basics/base_uint.h>
#include <xrpl/basics/partitioned_unordered_map.h>
#include <cstdint>
@@ -55,10 +56,7 @@ std::size_t constexpr oversizeMetaDataCap = 5200;
/** The maximum number of entries per directory page */
std::size_t constexpr dirNodeMaxEntries = 32;
/** The maximum number of pages allowed in a directory
Made obsolete by fixDirectoryLimit amendment.
*/
/** The maximum number of pages allowed in a directory */
std::uint64_t constexpr dirNodeMaxPages = 262144;
/** The maximum number of items in an NFT page */
@@ -181,20 +179,6 @@ std::size_t constexpr permissionMaxSize = 10;
/** The maximum number of transactions that can be in a batch. */
std::size_t constexpr maxBatchTxCount = 8;
/** EC ElGamal ciphertext length 33-byte */
std::size_t constexpr ecGamalEncryptedLength = 33;
/** EC ElGamal ciphertext length: two 33-byte components concatenated */
std::size_t constexpr ecGamalEncryptedTotalLength = 66;
/** Length of equality ZKProof */
std::size_t constexpr ecEqualityProofLength = 98;
/** Length of EC public key */
std::size_t constexpr ecPubKeyLength = 64;
/** Length of EC private key */
std::size_t constexpr ecPrivKeyLength = 32;
} // namespace ripple
#endif

View File

@@ -21,7 +21,6 @@
#define RIPPLE_PROTOCOL_PUBLICKEY_H_INCLUDED
#include <xrpl/basics/Slice.h>
#include <xrpl/beast/net/IPEndpoint.h>
#include <xrpl/protocol/KeyType.h>
#include <xrpl/protocol/STExchange.h>
#include <xrpl/protocol/UintTypes.h>
@@ -265,24 +264,6 @@ calcNodeID(PublicKey const&);
AccountID
calcAccountID(PublicKey const& pk);
inline std::string
getFingerprint(
beast::IP::Endpoint const& address,
std::optional<PublicKey> const& publicKey = std::nullopt,
std::optional<std::string> const& id = std::nullopt)
{
std::stringstream ss;
ss << "IP Address: " << address;
if (publicKey.has_value())
{
ss << ", Public Key: " << toBase58(TokenType::NodePublic, *publicKey);
}
if (id.has_value())
{
ss << ", Id: " << id.value();
}
return ss.str();
}
} // namespace ripple
//------------------------------------------------------------------------------

View File

@@ -22,7 +22,6 @@
#include <xrpl/basics/safe_cast.h>
#include <xrpl/json/json_value.h>
#include <xrpl/protocol/Units.h>
#include <cstdint>
#include <map>
@@ -72,10 +71,8 @@ class STCurrency;
STYPE(STI_VL, 7) \
STYPE(STI_ACCOUNT, 8) \
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_ARRAY, 15) \
\
@@ -151,10 +148,8 @@ public:
sMD_ChangeNew = 0x02, // new value when it changes
sMD_DeleteFinal = 0x04, // final value when it is deleted
sMD_Create = 0x08, // value when it's created
sMD_Always = 0x10, // value when node containing it is affected at all
sMD_BaseTen = 0x20, // value is treated as base 10, overriding behavior
sMD_PseudoAccount = 0x40, // if this field is set in an ACCOUNT_ROOT
// _only_, then it is a pseudo-account
sMD_Always = 0x10, // value when node containing it is affected at all
sMD_BaseTen = 0x20,
sMD_Default =
sMD_ChangeOrig | sMD_ChangeNew | sMD_DeleteFinal | sMD_Create
};
@@ -189,7 +184,7 @@ public:
char const* fn,
int meta = sMD_Default,
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&
getField(int fieldCode);
@@ -302,7 +297,7 @@ public:
static int
compare(SField const& f1, SField const& f2);
static std::unordered_map<int, SField const*> const&
static std::map<int, SField const*> const&
getKnownCodeToField()
{
return knownCodeToField;
@@ -310,8 +305,7 @@ public:
private:
static int num;
static std::unordered_map<int, SField const*> knownCodeToField;
static std::unordered_map<std::string, SField const*> knownNameToField;
static std::map<int, SField const*> knownCodeToField;
};
/** A field with a type known at compile time. */
@@ -358,9 +352,6 @@ using SF_UINT256 = TypedField<STBitString<256>>;
using SF_UINT384 = TypedField<STBitString<384>>;
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_AMOUNT = TypedField<STAmount>;
using SF_ISSUE = TypedField<STIssue>;

View File

@@ -709,6 +709,37 @@ canAdd(STAmount const& amt1, STAmount const& amt2);
bool
canSubtract(STAmount const& amt1, STAmount const& amt2);
// Since `canonicalize` does not have access to a ledger, this is needed to put
// the low-level routine stAmountCanonicalize on an amendment switch. Only
// transactions need to use this switchover. Outside of a transaction it's safe
// to unconditionally use the new behavior.
bool
getSTAmountCanonicalizeSwitchover();
void
setSTAmountCanonicalizeSwitchover(bool v);
/** RAII class to set and restore the STAmount canonicalize switchover.
*/
class STAmountSO
{
public:
explicit STAmountSO(bool v) : saved_(getSTAmountCanonicalizeSwitchover())
{
setSTAmountCanonicalizeSwitchover(v);
}
~STAmountSO()
{
setSTAmountCanonicalizeSwitchover(saved_);
}
private:
bool saved_;
};
} // namespace ripple
//------------------------------------------------------------------------------

View File

@@ -81,8 +81,6 @@ using STUInt16 = STInteger<std::uint16_t>;
using STUInt32 = STInteger<std::uint32_t>;
using STUInt64 = STInteger<std::uint64_t>;
using STInt32 = STInteger<std::int32_t>;
template <typename Integer>
inline STInteger<Integer>::STInteger(Integer v) : value_(v)
{

View File

@@ -26,9 +26,7 @@
namespace ripple {
class Rules;
namespace test {
class Invariants_test;
}
class STLedgerEntry final : public STObject, public CountedObject<STLedgerEntry>
{
@@ -38,8 +36,6 @@ class STLedgerEntry final : public STObject, public CountedObject<STLedgerEntry>
public:
using pointer = std::shared_ptr<STLedgerEntry>;
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. */
explicit STLedgerEntry(Keylet const& k);
@@ -58,7 +54,7 @@ public:
getText() const override;
Json::Value
getJson(JsonOptions options = JsonOptions::none) const override;
getJson(JsonOptions options) const override;
/** Returns the 'key' (or 'index') of this item.
The key identifies this entry's position in
@@ -88,8 +84,7 @@ private:
void
setSLEType();
friend test::Invariants_test; // this test wants access to the private
// type_
friend Invariants_test; // this test wants access to the private type_
STBase*
copy(std::size_t n, void* buf) const override;

View File

@@ -25,6 +25,7 @@
#include <xrpl/basics/chrono.h>
#include <xrpl/basics/contract.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/protocol/FeeUnits.h>
#include <xrpl/protocol/HashPrefix.h>
#include <xrpl/protocol/SOTemplate.h>
#include <xrpl/protocol/STAmount.h>
@@ -33,7 +34,6 @@
#include <xrpl/protocol/STIssue.h>
#include <xrpl/protocol/STPathSet.h>
#include <xrpl/protocol/STVector256.h>
#include <xrpl/protocol/Units.h>
#include <xrpl/protocol/detail/STVar.h>
#include <boost/iterator/transform_iterator.hpp>
@@ -231,8 +231,6 @@ public:
getFieldH192(SField const& field) const;
uint256
getFieldH256(SField const& field) const;
std::int32_t
getFieldI32(SField const& field) const;
AccountID
getAccountID(SField const& field) const;
@@ -244,9 +242,6 @@ public:
getFieldPathSet(SField const& field) const;
STVector256 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&
getFieldArray(SField const& field) const;
STCurrency const&
@@ -370,8 +365,6 @@ public:
void
setFieldH256(SField const& field, uint256 const&);
void
setFieldI32(SField const& field, std::int32_t);
void
setFieldVL(SField const& field, Blob const&);
void
setFieldVL(SField const& field, Slice const&);
@@ -393,8 +386,6 @@ public:
setFieldV256(SField const& field, STVector256 const& v);
void
setFieldArray(SField const& field, STArray const& v);
void
setFieldObject(SField const& field, STObject const& v);
template <class Tag>
void

View File

@@ -54,6 +54,34 @@ public:
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
#endif

View File

@@ -87,14 +87,8 @@ public:
getFullText() const override;
// Outer transaction functions / signature functions.
static Blob
getSignature(STObject const& sigObject);
Blob
getSignature() const
{
return getSignature(*this);
}
getSignature() const;
uint256
getSigningHash() const;
@@ -125,20 +119,13 @@ public:
getJson(JsonOptions options, bool binary) const;
void
sign(
PublicKey const& publicKey,
SecretKey const& secretKey,
std::optional<std::reference_wrapper<SField const>> signatureTarget =
{});
enum class RequireFullyCanonicalSig : bool { no, yes };
sign(PublicKey const& publicKey, SecretKey const& secretKey);
/** 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.
*/
enum class RequireFullyCanonicalSig : bool { no, yes };
Expected<void, std::string>
checkSign(RequireFullyCanonicalSig requireCanonicalSig, Rules const& rules)
const;
@@ -163,34 +150,17 @@ public:
char status,
std::string const& escapedMetaData) const;
std::vector<uint256> const&
std::vector<uint256>
getBatchTransactionIDs() const;
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>
checkSign(
RequireFullyCanonicalSig requireCanonicalSig,
Rules const& rules,
STObject const& sigObject) const;
Expected<void, std::string>
checkSingleSign(
RequireFullyCanonicalSig requireCanonicalSig,
STObject const& sigObject) const;
checkSingleSign(RequireFullyCanonicalSig requireCanonicalSig) const;
Expected<void, std::string>
checkMultiSign(
RequireFullyCanonicalSig requireCanonicalSig,
Rules const& rules,
STObject const& sigObject) const;
Rules const& rules) const;
Expected<void, std::string>
checkBatchSingleSign(
@@ -209,7 +179,7 @@ private:
move(std::size_t n, void* buf) override;
friend class detail::STVar;
mutable std::vector<uint256> batchTxnIds_;
mutable std::vector<uint256> batch_txn_ids_;
};
bool

View File

@@ -22,10 +22,10 @@
#include <xrpl/basics/Log.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/protocol/FeeUnits.h>
#include <xrpl/protocol/PublicKey.h>
#include <xrpl/protocol/STObject.h>
#include <xrpl/protocol/SecretKey.h>
#include <xrpl/protocol/Units.h>
#include <cstdint>
#include <optional>

View File

@@ -73,8 +73,14 @@ static constexpr std::uint32_t XRP_LEDGER_EARLIEST_SEQ{32570u};
* used in asserts and tests. */
static constexpr std::uint32_t XRP_LEDGER_EARLIEST_FEES{562177u};
/** The minimum amount of support an amendment should have. */
constexpr std::ratio<80, 100> amendmentMajorityCalcThreshold;
/** The minimum amount of support an amendment should have.
@note This value is used by legacy code and will become obsolete
once the fixAmendmentMajorityCalc amendment activates.
*/
constexpr std::ratio<204, 256> preFixAmendmentMajorityCalcThreshold;
constexpr std::ratio<80, 100> postFixAmendmentMajorityCalcThreshold;
/** The minimum amount of time an amendment must hold a majority */
constexpr std::chrono::seconds const defaultAmendmentMajorityTime = weeks{2};

View File

@@ -141,7 +141,6 @@ enum TEMcodes : TERUnderlyingType {
temARRAY_TOO_LARGE,
temBAD_TRANSFER_FEE,
temINVALID_INNER_BATCH,
temBAD_CIPHERTEXT,
};
//------------------------------------------------------------------------------
@@ -226,9 +225,8 @@ enum TERcodes : TERUnderlyingType {
terQUEUED, // Transaction is being held in TxQ until fee drops
terPRE_TICKET, // Ticket is not yet in ledger but might be on its way
terNO_AMM, // AMM doesn't exist for the asset pair
terADDRESS_COLLISION, // Failed to allocate AccountID when trying to
// create a pseudo-account
terNO_DELEGATE_PERMISSION, // Delegate does not have permission
terADDRESS_COLLISION, // Failed to allocate AccountID when trying to
// create a pseudo-account
};
//------------------------------------------------------------------------------
@@ -363,11 +361,7 @@ enum TECcodes : TERUnderlyingType {
tecLIMIT_EXCEEDED = 195,
tecPSEUDO_ACCOUNT = 196,
tecPRECISION_LOSS = 197,
// DEPRECATED: This error code tecNO_DELEGATE_PERMISSION is reserved for
// backward compatibility with historical data on non-prod networks, can be
// reclaimed after those networks reset.
tecNO_DELEGATE_PERMISSION = 198,
tecBAD_PROOF = 199
};
//------------------------------------------------------------------------------
@@ -679,8 +673,7 @@ isTerRetry(TER x) noexcept
inline bool
isTesSuccess(TER x) noexcept
{
// Makes use of TERSubset::operator bool()
return !(x);
return (x == tesSUCCESS);
}
inline bool

View File

@@ -127,8 +127,6 @@ constexpr std::uint32_t tfTrustSetPermissionMask = ~(tfUniversal | tfSetfAuth |
// EnableAmendment flags:
constexpr std::uint32_t tfGotMajority = 0x00010000;
constexpr std::uint32_t tfLostMajority = 0x00020000;
constexpr std::uint32_t tfChangeMask =
~( tfUniversal | tfGotMajority | tfLostMajority);
// PaymentChannelClaim flags:
constexpr std::uint32_t tfRenew = 0x00010000;
@@ -143,31 +141,15 @@ constexpr std::uint32_t const tfTransferable = 0x00000008;
constexpr std::uint32_t const tfMutable = 0x00000010;
// MPTokenIssuanceCreate flags:
// Note: tf/lsfMPTLocked is intentionally omitted, since this transaction
// is not allowed to modify it.
// NOTE - there is intentionally no flag here for lsfMPTLocked, which this transaction cannot mutate.
constexpr std::uint32_t const tfMPTCanLock = lsfMPTCanLock;
constexpr std::uint32_t const tfMPTRequireAuth = lsfMPTRequireAuth;
constexpr std::uint32_t const tfMPTCanEscrow = lsfMPTCanEscrow;
constexpr std::uint32_t const tfMPTCanTrade = lsfMPTCanTrade;
constexpr std::uint32_t const tfMPTCanTransfer = lsfMPTCanTransfer;
constexpr std::uint32_t const tfMPTCanClawback = lsfMPTCanClawback;
constexpr std::uint32_t const tfMPTNoConfidentialTransfer = lsfMPTNoConfidentialTransfer;
constexpr std::uint32_t const tfMPTokenIssuanceCreateMask =
~(tfUniversal | tfMPTCanLock | tfMPTRequireAuth | tfMPTCanEscrow | tfMPTCanTrade | tfMPTCanTransfer | tfMPTCanClawback | tfMPTNoConfidentialTransfer);
// 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);
~(tfUniversal | tfMPTCanLock | tfMPTRequireAuth | tfMPTCanEscrow | tfMPTCanTrade | tfMPTCanTransfer | tfMPTCanClawback);
// MPTokenAuthorize flags:
constexpr std::uint32_t const tfMPTUnauthorize = 0x00000001;
@@ -179,25 +161,6 @@ constexpr std::uint32_t const tfMPTUnlock = 0x00000002;
constexpr std::uint32_t const tfMPTokenIssuanceSetMask = ~(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:
constexpr std::uint32_t const tfMPTokenIssuanceDestroyMask = ~tfUniversal;

View File

@@ -33,35 +33,51 @@ namespace ripple {
class TxMeta
{
private:
struct CtorHelper
{
explicit CtorHelper() = default;
};
template <class T>
TxMeta(
uint256 const& txID,
std::uint32_t ledger,
T const& data,
CtorHelper);
public:
TxMeta(uint256 const& transactionID, std::uint32_t ledger);
TxMeta(
uint256 const& transactionID,
std::uint32_t ledger,
std::optional<uint256> parentBatchId = std::nullopt);
TxMeta(uint256 const& txID, std::uint32_t ledger, Blob const&);
TxMeta(uint256 const& txID, std::uint32_t ledger, std::string const&);
TxMeta(uint256 const& txID, std::uint32_t ledger, STObject const&);
uint256 const&
getTxID() const
{
return transactionID_;
return mTransactionID;
}
std::uint32_t
getLgrSeq() const
{
return ledgerSeq_;
return mLedger;
}
int
getResult() const
{
return result_;
return mResult;
}
TER
getResultTER() const
{
return TER::fromInt(result_);
return TER::fromInt(mResult);
}
std::uint32_t
getIndex() const
{
return index_;
return mIndex;
}
void
@@ -88,52 +104,66 @@ public:
STArray&
getNodes()
{
return nodes_;
return (mNodes);
}
STArray const&
getNodes() const
{
return nodes_;
return (mNodes);
}
void
setAdditionalFields(STObject const& obj)
setDeliveredAmount(STAmount const& delivered)
{
if (obj.isFieldPresent(sfDeliveredAmount))
deliveredAmount_ = obj.getFieldAmount(sfDeliveredAmount);
if (obj.isFieldPresent(sfParentBatchID))
parentBatchID_ = obj.getFieldH256(sfParentBatchID);
mDelivered = delivered;
}
std::optional<STAmount> const&
STAmount
getDeliveredAmount() const
{
return deliveredAmount_;
XRPL_ASSERT(
hasDeliveredAmount(),
"ripple::TxMeta::getDeliveredAmount : non-null delivered amount");
return *mDelivered;
}
bool
hasDeliveredAmount() const
{
return static_cast<bool>(mDelivered);
}
void
setDeliveredAmount(std::optional<STAmount> const& amount)
setParentBatchId(uint256 const& parentBatchId)
{
deliveredAmount_ = amount;
mParentBatchId = parentBatchId;
}
void
setParentBatchID(std::optional<uint256> const& id)
uint256
getParentBatchId() const
{
parentBatchID_ = id;
XRPL_ASSERT(
hasParentBatchId(),
"ripple::TxMeta::getParentBatchId : non-null batch id");
return *mParentBatchId;
}
bool
hasParentBatchId() const
{
return static_cast<bool>(mParentBatchId);
}
private:
uint256 transactionID_;
std::uint32_t ledgerSeq_;
std::uint32_t index_;
int result_;
uint256 mTransactionID;
std::uint32_t mLedger;
std::uint32_t mIndex;
int mResult;
std::optional<STAmount> deliveredAmount_;
std::optional<uint256> parentBatchID_;
std::optional<STAmount> mDelivered;
std::optional<uint256> mParentBatchId;
STArray nodes_;
STArray mNodes;
};
} // namespace ripple

View File

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

View File

@@ -24,7 +24,7 @@
#include <xrpl/basics/contract.h>
#include <xrpl/beast/utility/Zero.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/operators.hpp>
@@ -42,7 +42,7 @@ class XRPAmount : private boost::totally_ordered<XRPAmount>,
private boost::additive<XRPAmount, std::int64_t>
{
public:
using unit_type = unit::dropTag;
using unit_type = feeunit::dropTag;
using value_type = std::int64_t;
private:

View File

@@ -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
// the a null set of numbers to be zero, so the remainder is also zero.
// LCOV_EXCL_START
UNREACHABLE(
"ripple::b58_fast::detail::inplace_bigint_div_rem : empty "
"numerator");
return 0;
// LCOV_EXCL_STOP
}
auto to_u128 = [](std::uint64_t high,

View File

@@ -29,15 +29,12 @@
// Add new amendments to the top of this list.
// Keep it sorted in reverse chronological order.
// If you add an amendment here, then do not forget to increment `numFeatures`
// in include/xrpl/protocol/Feature.h.
XRPL_FEATURE(ConfidentialTransfer, Supported::no, VoteBehavior::DefaultNo)
XRPL_FEATURE(PermissionDelegationV1_1, 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 (PriceOracleOrder, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (MPTDeliveredAmount, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (DelegateV1_1, Supported::no, VoteBehavior::DefaultNo)
XRPL_FIX (PriceOracleOrder, Supported::no, VoteBehavior::DefaultNo)
XRPL_FIX (MPTDeliveredAmount, Supported::no, VoteBehavior::DefaultNo)
XRPL_FIX (AMMClawbackRounding, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(TokenEscrow, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (EnforceNFTokenTrustlineV2, Supported::yes, VoteBehavior::DefaultNo)
@@ -45,6 +42,7 @@ XRPL_FIX (AMMv1_3, Supported::yes, VoteBehavior::DefaultNo
XRPL_FEATURE(PermissionedDEX, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(Batch, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(SingleAssetVault, Supported::no, VoteBehavior::DefaultNo)
XRPL_FEATURE(PermissionDelegation, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (PayChanCancelAfter, Supported::yes, VoteBehavior::DefaultNo)
// Check flags in Credential transactions
XRPL_FIX (InvalidTxFlags, Supported::yes, VoteBehavior::DefaultNo)
@@ -78,24 +76,45 @@ XRPL_FIX (DisallowIncomingV1, Supported::yes, VoteBehavior::DefaultNo
XRPL_FEATURE(XChainBridge, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(AMM, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(Clawback, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (ReducedOffersV1, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (NFTokenRemint, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (NonFungibleTokensV1_2, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (UniversalNumber, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(XRPFees, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(DisallowIncoming, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(ImmediateOfferKilled, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (RemoveNFTokenAutoTrustLine, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (TrustLinesToSelf, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(NonFungibleTokensV1_1, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(ExpandedSignerList, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(CheckCashMakesTrustLine, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (RmSmallIncreasedQOffers, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (STAmountCanonicalize, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(FlowSortStrands, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(TicketBatch, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(NegativeUNL, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (AmendmentMajorityCalc, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(HardenedValidations, Supported::yes, VoteBehavior::DefaultYes)
// fix1781: XRPEndpointSteps should be included in the circular payment check
XRPL_FIX (1781, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(RequireFullyCanonicalSig, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (QualityUpperBound, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(DeletableAccounts, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (PayChanRecipientOwnerDir, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (CheckThreading, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (MasterKeyAsRegularKey, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (TakerDryOfferRemoval, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(MultiSignReserve, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (1578, Supported::yes, VoteBehavior::DefaultYes)
// fix1515: Use liquidity from strands that consume max offers, but mark as dry
XRPL_FIX (1515, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(DepositPreauth, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (1623, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (1543, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (1571, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(Checks, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(DepositAuth, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FIX (1513, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(Flow, Supported::yes, VoteBehavior::DefaultYes)
// The following amendments are obsolete, but must remain supported
@@ -109,46 +128,28 @@ XRPL_FEATURE(Flow, Supported::yes, VoteBehavior::DefaultYe
//
// If a feature remains obsolete for long enough that no clients are able
// to vote for it, the feature can be removed (entirely?) from the code.
XRPL_FIX (NFTokenNegOffer, Supported::yes, VoteBehavior::Obsolete)
XRPL_FIX (NFTokenDirV1, Supported::yes, VoteBehavior::Obsolete)
XRPL_FEATURE(NonFungibleTokensV1, Supported::yes, VoteBehavior::Obsolete)
XRPL_FEATURE(CryptoConditionsSuite, Supported::yes, VoteBehavior::Obsolete)
// The following amendments have been active for at least two years. Their
// pre-amendment code has been removed and the identifiers are deprecated.
// All known amendments and amendments that may appear in a validated ledger
// must be registered either here or above with the "active" amendments
//
// Please keep this list sorted alphabetically for convenience.
XRPL_RETIRE(fix1201)
// All known amendments and amendments that may appear in a validated
// ledger must be registered either here or above with the "active" amendments
XRPL_RETIRE(MultiSign)
XRPL_RETIRE(TrustSetAuth)
XRPL_RETIRE(FeeEscalation)
XRPL_RETIRE(PayChan)
XRPL_RETIRE(CryptoConditions)
XRPL_RETIRE(TickSize)
XRPL_RETIRE(fix1368)
XRPL_RETIRE(Escrow)
XRPL_RETIRE(fix1373)
XRPL_RETIRE(EnforceInvariants)
XRPL_RETIRE(SortedDirectories)
XRPL_RETIRE(fix1201)
XRPL_RETIRE(fix1512)
XRPL_RETIRE(fix1513)
XRPL_RETIRE(fix1515)
XRPL_RETIRE(fix1523)
XRPL_RETIRE(fix1528)
XRPL_RETIRE(fix1543)
XRPL_RETIRE(fix1571)
XRPL_RETIRE(fix1578)
XRPL_RETIRE(fix1623)
XRPL_RETIRE(fix1781)
XRPL_RETIRE(fixAmendmentMajorityCalc)
XRPL_RETIRE(fixCheckThreading)
XRPL_RETIRE(fixNonFungibleTokensV1_2)
XRPL_RETIRE(fixNFTokenRemint)
XRPL_RETIRE(fixMasterKeyAsRegularKey)
XRPL_RETIRE(fixQualityUpperBound)
XRPL_RETIRE(fixReducedOffersV1)
XRPL_RETIRE(fixRmSmallIncreasedQOffers)
XRPL_RETIRE(fixSTAmountCanonicalize)
XRPL_RETIRE(fixTakerDryOfferRemoval)
XRPL_RETIRE(CryptoConditions)
XRPL_RETIRE(Escrow)
XRPL_RETIRE(EnforceInvariants)
XRPL_RETIRE(FeeEscalation)
XRPL_RETIRE(FlowCross)
XRPL_RETIRE(ImmediateOfferKilled)
XRPL_RETIRE(MultiSign)
XRPL_RETIRE(NonFungibleTokensV1_1)
XRPL_RETIRE(PayChan)
XRPL_RETIRE(SortedDirectories)
XRPL_RETIRE(TickSize)
XRPL_RETIRE(TrustSetAuth)

View File

@@ -120,7 +120,6 @@ LEDGER_ENTRY(ltNFTOKEN_PAGE, 0x0050, NFTokenPage, nft_page, ({
// All fields are soeREQUIRED because there is always a SignerEntries.
// If there are no SignerEntries the node is deleted.
LEDGER_ENTRY(ltSIGNER_LIST, 0x0053, SignerList, signer_list, ({
{sfOwner, soeOPTIONAL},
{sfOwnerNode, soeREQUIRED},
{sfSignerQuorum, soeREQUIRED},
{sfSignerEntries, soeREQUIRED},
@@ -189,7 +188,7 @@ LEDGER_ENTRY(ltDIR_NODE, 0x0064, DirectoryNode, directory, ({
{sfNFTokenID, soeOPTIONAL},
{sfPreviousTxnID, soeOPTIONAL},
{sfPreviousTxnLgrSeq, soeOPTIONAL},
{sfDomainID, soeOPTIONAL} // order book directories
{sfDomainID, soeOPTIONAL}
}))
/** The ledger object which lists details about amendments on the network.
@@ -344,7 +343,6 @@ LEDGER_ENTRY(ltXCHAIN_OWNED_CREATE_ACCOUNT_CLAIM_ID, 0x0074, XChainOwnedCreateAc
*/
LEDGER_ENTRY(ltESCROW, 0x0075, Escrow, escrow, ({
{sfAccount, soeREQUIRED},
{sfSequence, soeOPTIONAL},
{sfDestination, soeREQUIRED},
{sfAmount, soeREQUIRED},
{sfCondition, soeOPTIONAL},
@@ -367,7 +365,6 @@ LEDGER_ENTRY(ltESCROW, 0x0075, Escrow, escrow, ({
LEDGER_ENTRY(ltPAYCHAN, 0x0078, PayChannel, payment_channel, ({
{sfAccount, soeREQUIRED},
{sfDestination, soeREQUIRED},
{sfSequence, soeOPTIONAL},
{sfAmount, soeREQUIRED},
{sfBalance, soeREQUIRED},
{sfPublicKey, soeREQUIRED},
@@ -415,9 +412,6 @@ LEDGER_ENTRY(ltMPTOKEN_ISSUANCE, 0x007e, MPTokenIssuance, mpt_issuance, ({
{sfPreviousTxnID, soeREQUIRED},
{sfPreviousTxnLgrSeq, soeREQUIRED},
{sfDomainID, soeOPTIONAL},
{sfMutableFlags, soeDEFAULT},
{sfIssuerElGamalPublicKey, soeOPTIONAL},
{sfConfidentialOutstandingAmount, soeDEFAULT},
}))
/** A ledger object which tracks MPToken
@@ -431,11 +425,6 @@ LEDGER_ENTRY(ltMPTOKEN, 0x007f, MPToken, mptoken, ({
{sfOwnerNode, soeREQUIRED},
{sfPreviousTxnID, soeREQUIRED},
{sfPreviousTxnLgrSeq, soeREQUIRED},
{sfConfidentialBalanceInbox, soeOPTIONAL},
{sfConfidentialBalanceSpending, soeOPTIONAL},
{sfConfidentialBalanceVersion, soeDEFAULT},
{sfIssuerEncryptedBalance, soeOPTIONAL},
{sfHolderElGamalPublicKey, soeOPTIONAL},
}))
/** A ledger object which tracks Oracle
@@ -443,7 +432,6 @@ LEDGER_ENTRY(ltMPTOKEN, 0x007f, MPToken, mptoken, ({
*/
LEDGER_ENTRY(ltORACLE, 0x0080, Oracle, oracle, ({
{sfOwner, soeREQUIRED},
{sfOracleDocumentID, soeOPTIONAL},
{sfProvider, soeREQUIRED},
{sfPriceDataSeries, soeREQUIRED},
{sfAssetClass, soeREQUIRED},
@@ -464,7 +452,7 @@ LEDGER_ENTRY(ltCREDENTIAL, 0x0081, Credential, credential, ({
{sfExpiration, soeOPTIONAL},
{sfURI, soeOPTIONAL},
{sfIssuerNode, soeREQUIRED},
{sfSubjectNode, soeOPTIONAL},
{sfSubjectNode, soeREQUIRED},
{sfPreviousTxnID, soeREQUIRED},
{sfPreviousTxnLgrSeq, soeREQUIRED},
}))

View File

@@ -114,8 +114,6 @@ TYPED_SFIELD(sfVoteWeight, UINT32, 48)
TYPED_SFIELD(sfFirstNFTokenSequence, UINT32, 50)
TYPED_SFIELD(sfOracleDocumentID, UINT32, 51)
TYPED_SFIELD(sfPermissionValue, UINT32, 52)
TYPED_SFIELD(sfMutableFlags, UINT32, 53)
TYPED_SFIELD(sfConfidentialBalanceVersion, UINT32, 54)
// 64-bit integers (common)
TYPED_SFIELD(sfIndexNext, UINT64, 1)
@@ -147,7 +145,6 @@ TYPED_SFIELD(sfMPTAmount, UINT64, 26, SField::sMD_BaseTen|SFie
TYPED_SFIELD(sfIssuerNode, UINT64, 27)
TYPED_SFIELD(sfSubjectNode, UINT64, 28)
TYPED_SFIELD(sfLockedAmount, UINT64, 29, SField::sMD_BaseTen|SField::sMD_Default)
TYPED_SFIELD(sfConfidentialOutstandingAmount, UINT64, 30, SField::sMD_BaseTen|SField::sMD_Default)
// 128-bit
TYPED_SFIELD(sfEmailHash, UINT128, 1)
@@ -176,8 +173,7 @@ TYPED_SFIELD(sfNFTokenID, UINT256, 10)
TYPED_SFIELD(sfEmitParentTxnID, UINT256, 11)
TYPED_SFIELD(sfEmitNonce, UINT256, 12)
TYPED_SFIELD(sfEmitHookHash, UINT256, 13)
TYPED_SFIELD(sfAMMID, UINT256, 14,
SField::sMD_PseudoAccount | SField::sMD_Default)
TYPED_SFIELD(sfAMMID, UINT256, 14)
// 256-bit (uncommon)
TYPED_SFIELD(sfBookDirectory, UINT256, 16)
@@ -199,8 +195,7 @@ TYPED_SFIELD(sfHookHash, UINT256, 31)
TYPED_SFIELD(sfHookNamespace, UINT256, 32)
TYPED_SFIELD(sfHookSetTxnID, UINT256, 33)
TYPED_SFIELD(sfDomainID, UINT256, 34)
TYPED_SFIELD(sfVaultID, UINT256, 35,
SField::sMD_PseudoAccount | SField::sMD_Default)
TYPED_SFIELD(sfVaultID, UINT256, 35)
TYPED_SFIELD(sfParentBatchID, UINT256, 36)
// number (common)
@@ -210,12 +205,6 @@ TYPED_SFIELD(sfAssetsMaximum, NUMBER, 3)
TYPED_SFIELD(sfAssetsTotal, NUMBER, 4)
TYPED_SFIELD(sfLossUnrealized, NUMBER, 5)
// int32
// NOTE: Do not use `sfDummyInt32`. It's so far the only use of INT32
// in this file and has been defined here for test only.
// TODO: Replace `sfDummyInt32` with actually useful field.
TYPED_SFIELD(sfDummyInt32, INT32, 1) // for tests only
// currency amount (common)
TYPED_SFIELD(sfAmount, AMOUNT, 1)
TYPED_SFIELD(sfBalance, AMOUNT, 2)
@@ -286,16 +275,6 @@ TYPED_SFIELD(sfAssetClass, VL, 28)
TYPED_SFIELD(sfProvider, VL, 29)
TYPED_SFIELD(sfMPTokenMetadata, VL, 30)
TYPED_SFIELD(sfCredentialType, VL, 31)
TYPED_SFIELD(sfConfidentialBalanceInbox, VL, 32)
TYPED_SFIELD(sfConfidentialBalanceSpending, VL, 33)
TYPED_SFIELD(sfIssuerEncryptedBalance, VL, 34)
TYPED_SFIELD(sfIssuerElGamalPublicKey, VL, 35)
TYPED_SFIELD(sfHolderElGamalPublicKey, VL, 36)
TYPED_SFIELD(sfZKProof, VL, 37)
TYPED_SFIELD(sfHolderEncryptedAmount, VL, 38)
TYPED_SFIELD(sfIssuerEncryptedAmount, VL, 39)
TYPED_SFIELD(sfSenderEncryptedAmount, VL, 40)
TYPED_SFIELD(sfDestinationEncryptedAmount, VL, 41)
// account (common)
TYPED_SFIELD(sfAccount, ACCOUNT, 1)

View File

@@ -22,31 +22,16 @@
#endif
/**
* TRANSACTION(tag, value, name, delegatable, amendments, privileges, fields)
*
* To ease maintenance, you may replace any unneeded values with "..."
* e.g. #define TRANSACTION(tag, value, name, ...)
* TRANSACTION(tag, value, name, delegatable, amendments, fields)
*
* You must define a transactor class in the `ripple` namespace named `name`,
* and include its header alongside the TRANSACTOR definition using this
* format:
* #if TRANSACTION_INCLUDE
* # include <xrpld/app/tx/detail/HEADER.h>
* #endif
*
* The `privileges` parameter of the TRANSACTION macro is a bitfield
* defining which operations the transaction can perform.
* The values are defined and used in InvariantCheck.cpp
* and include its header in `src/xrpld/app/tx/detail/applySteps.cpp`.
*/
/** This transaction type executes a payment. */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/Payment.h>
#endif
TRANSACTION(ttPAYMENT, 0, Payment,
Delegation::delegatable,
uint256{},
createAcct,
({
{sfDestination, soeREQUIRED},
{sfAmount, soeREQUIRED, soeMPTSupported},
@@ -60,13 +45,9 @@ TRANSACTION(ttPAYMENT, 0, Payment,
}))
/** This transaction type creates an escrow object. */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/Escrow.h>
#endif
TRANSACTION(ttESCROW_CREATE, 1, EscrowCreate,
Delegation::delegatable,
uint256{},
noPriv,
({
{sfDestination, soeREQUIRED},
{sfAmount, soeREQUIRED, soeMPTSupported},
@@ -80,7 +61,6 @@ TRANSACTION(ttESCROW_CREATE, 1, EscrowCreate,
TRANSACTION(ttESCROW_FINISH, 2, EscrowFinish,
Delegation::delegatable,
uint256{},
noPriv,
({
{sfOwner, soeREQUIRED},
{sfOfferSequence, soeREQUIRED},
@@ -91,13 +71,9 @@ TRANSACTION(ttESCROW_FINISH, 2, EscrowFinish,
/** This transaction type adjusts various account settings. */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/SetAccount.h>
#endif
TRANSACTION(ttACCOUNT_SET, 3, AccountSet,
Delegation::notDelegatable,
uint256{},
noPriv,
({
{sfEmailHash, soeOPTIONAL},
{sfWalletLocator, soeOPTIONAL},
@@ -112,26 +88,18 @@ TRANSACTION(ttACCOUNT_SET, 3, AccountSet,
}))
/** This transaction type cancels an existing escrow. */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/Escrow.h>
#endif
TRANSACTION(ttESCROW_CANCEL, 4, EscrowCancel,
Delegation::delegatable,
uint256{},
noPriv,
({
{sfOwner, soeREQUIRED},
{sfOfferSequence, soeREQUIRED},
}))
/** This transaction type sets or clears an account's "regular key". */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/SetRegularKey.h>
#endif
TRANSACTION(ttREGULAR_KEY_SET, 5, SetRegularKey,
Delegation::notDelegatable,
uint256{},
noPriv,
({
{sfRegularKey, soeOPTIONAL},
}))
@@ -139,13 +107,9 @@ TRANSACTION(ttREGULAR_KEY_SET, 5, SetRegularKey,
// 6 deprecated
/** This transaction type creates an offer to trade one asset for another. */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/CreateOffer.h>
#endif
TRANSACTION(ttOFFER_CREATE, 7, OfferCreate,
Delegation::delegatable,
uint256{},
noPriv,
({
{sfTakerPays, soeREQUIRED},
{sfTakerGets, soeREQUIRED},
@@ -155,13 +119,9 @@ TRANSACTION(ttOFFER_CREATE, 7, OfferCreate,
}))
/** This transaction type cancels existing offers to trade one asset for another. */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/CancelOffer.h>
#endif
TRANSACTION(ttOFFER_CANCEL, 8, OfferCancel,
Delegation::delegatable,
uint256{},
noPriv,
({
{sfOfferSequence, soeREQUIRED},
}))
@@ -169,13 +129,9 @@ TRANSACTION(ttOFFER_CANCEL, 8, OfferCancel,
// 9 deprecated
/** This transaction type creates a new set of tickets. */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/CreateTicket.h>
#endif
TRANSACTION(ttTICKET_CREATE, 10, TicketCreate,
Delegation::delegatable,
featureTicketBatch,
noPriv,
({
{sfTicketCount, soeREQUIRED},
}))
@@ -185,26 +141,18 @@ TRANSACTION(ttTICKET_CREATE, 10, TicketCreate,
/** This transaction type modifies the signer list associated with an account. */
// The SignerEntries are optional because a SignerList is deleted by
// setting the SignerQuorum to zero and omitting SignerEntries.
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/SetSignerList.h>
#endif
TRANSACTION(ttSIGNER_LIST_SET, 12, SignerListSet,
Delegation::notDelegatable,
uint256{},
noPriv,
({
{sfSignerQuorum, soeREQUIRED},
{sfSignerEntries, soeOPTIONAL},
}))
/** This transaction type creates a new unidirectional XRP payment channel. */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/PayChan.h>
#endif
TRANSACTION(ttPAYCHAN_CREATE, 13, PaymentChannelCreate,
Delegation::delegatable,
uint256{},
noPriv,
({
{sfDestination, soeREQUIRED},
{sfAmount, soeREQUIRED},
@@ -218,7 +166,6 @@ TRANSACTION(ttPAYCHAN_CREATE, 13, PaymentChannelCreate,
TRANSACTION(ttPAYCHAN_FUND, 14, PaymentChannelFund,
Delegation::delegatable,
uint256{},
noPriv,
({
{sfChannel, soeREQUIRED},
{sfAmount, soeREQUIRED},
@@ -229,7 +176,6 @@ TRANSACTION(ttPAYCHAN_FUND, 14, PaymentChannelFund,
TRANSACTION(ttPAYCHAN_CLAIM, 15, PaymentChannelClaim,
Delegation::delegatable,
uint256{},
noPriv,
({
{sfChannel, soeREQUIRED},
{sfAmount, soeOPTIONAL},
@@ -240,13 +186,9 @@ TRANSACTION(ttPAYCHAN_CLAIM, 15, PaymentChannelClaim,
}))
/** This transaction type creates a new check. */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/CreateCheck.h>
#endif
TRANSACTION(ttCHECK_CREATE, 16, CheckCreate,
Delegation::delegatable,
featureChecks,
noPriv,
({
{sfDestination, soeREQUIRED},
{sfSendMax, soeREQUIRED},
@@ -256,13 +198,9 @@ TRANSACTION(ttCHECK_CREATE, 16, CheckCreate,
}))
/** This transaction type cashes an existing check. */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/CashCheck.h>
#endif
TRANSACTION(ttCHECK_CASH, 17, CheckCash,
Delegation::delegatable,
featureChecks,
noPriv,
({
{sfCheckID, soeREQUIRED},
{sfAmount, soeOPTIONAL},
@@ -270,25 +208,17 @@ TRANSACTION(ttCHECK_CASH, 17, CheckCash,
}))
/** This transaction type cancels an existing check. */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/CancelCheck.h>
#endif
TRANSACTION(ttCHECK_CANCEL, 18, CheckCancel,
Delegation::delegatable,
featureChecks,
noPriv,
({
{sfCheckID, soeREQUIRED},
}))
/** This transaction type grants or revokes authorization to transfer funds. */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/DepositPreauth.h>
#endif
TRANSACTION(ttDEPOSIT_PREAUTH, 19, DepositPreauth,
Delegation::delegatable,
featureDepositPreauth,
noPriv,
({
{sfAuthorize, soeOPTIONAL},
{sfUnauthorize, soeOPTIONAL},
@@ -297,13 +227,9 @@ TRANSACTION(ttDEPOSIT_PREAUTH, 19, DepositPreauth,
}))
/** This transaction type modifies a trustline between two accounts. */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/SetTrust.h>
#endif
TRANSACTION(ttTRUST_SET, 20, TrustSet,
Delegation::delegatable,
uint256{},
noPriv,
({
{sfLimitAmount, soeOPTIONAL},
{sfQualityIn, soeOPTIONAL},
@@ -311,13 +237,9 @@ TRANSACTION(ttTRUST_SET, 20, TrustSet,
}))
/** This transaction type deletes an existing account. */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/DeleteAccount.h>
#endif
TRANSACTION(ttACCOUNT_DELETE, 21, AccountDelete,
Delegation::notDelegatable,
featureDeletableAccounts,
mustDeleteAcct,
uint256{},
({
{sfDestination, soeREQUIRED},
{sfDestinationTag, soeOPTIONAL},
@@ -327,13 +249,9 @@ TRANSACTION(ttACCOUNT_DELETE, 21, AccountDelete,
// 22 reserved
/** This transaction mints a new NFT. */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/NFTokenMint.h>
#endif
TRANSACTION(ttNFTOKEN_MINT, 25, NFTokenMint,
Delegation::delegatable,
uint256{},
changeNFTCounts,
featureNonFungibleTokensV1,
({
{sfNFTokenTaxon, soeREQUIRED},
{sfTransferFee, soeOPTIONAL},
@@ -345,26 +263,18 @@ TRANSACTION(ttNFTOKEN_MINT, 25, NFTokenMint,
}))
/** This transaction burns (i.e. destroys) an existing NFT. */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/NFTokenBurn.h>
#endif
TRANSACTION(ttNFTOKEN_BURN, 26, NFTokenBurn,
Delegation::delegatable,
uint256{},
changeNFTCounts,
featureNonFungibleTokensV1,
({
{sfNFTokenID, soeREQUIRED},
{sfOwner, soeOPTIONAL},
}))
/** This transaction creates a new offer to buy or sell an NFT. */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/NFTokenCreateOffer.h>
#endif
TRANSACTION(ttNFTOKEN_CREATE_OFFER, 27, NFTokenCreateOffer,
Delegation::delegatable,
uint256{},
noPriv,
featureNonFungibleTokensV1,
({
{sfNFTokenID, soeREQUIRED},
{sfAmount, soeREQUIRED},
@@ -374,25 +284,17 @@ TRANSACTION(ttNFTOKEN_CREATE_OFFER, 27, NFTokenCreateOffer,
}))
/** This transaction cancels an existing offer to buy or sell an existing NFT. */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/NFTokenCancelOffer.h>
#endif
TRANSACTION(ttNFTOKEN_CANCEL_OFFER, 28, NFTokenCancelOffer,
Delegation::delegatable,
uint256{},
noPriv,
featureNonFungibleTokensV1,
({
{sfNFTokenOffers, soeREQUIRED},
}))
/** This transaction accepts an existing offer to buy or sell an existing NFT. */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/NFTokenAcceptOffer.h>
#endif
TRANSACTION(ttNFTOKEN_ACCEPT_OFFER, 29, NFTokenAcceptOffer,
Delegation::delegatable,
uint256{},
noPriv,
featureNonFungibleTokensV1,
({
{sfNFTokenBuyOffer, soeOPTIONAL},
{sfNFTokenSellOffer, soeOPTIONAL},
@@ -400,26 +302,18 @@ TRANSACTION(ttNFTOKEN_ACCEPT_OFFER, 29, NFTokenAcceptOffer,
}))
/** This transaction claws back issued tokens. */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/Clawback.h>
#endif
TRANSACTION(ttCLAWBACK, 30, Clawback,
Delegation::delegatable,
featureClawback,
noPriv,
({
{sfAmount, soeREQUIRED, soeMPTSupported},
{sfHolder, soeOPTIONAL},
}))
/** This transaction claws back tokens from an AMM pool. */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/AMMClawback.h>
#endif
TRANSACTION(ttAMM_CLAWBACK, 31, AMMClawback,
Delegation::delegatable,
featureAMMClawback,
mayDeleteAcct | overrideFreeze,
({
{sfHolder, soeREQUIRED},
{sfAsset, soeREQUIRED},
@@ -428,13 +322,9 @@ TRANSACTION(ttAMM_CLAWBACK, 31, AMMClawback,
}))
/** This transaction type creates an AMM instance */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/AMMCreate.h>
#endif
TRANSACTION(ttAMM_CREATE, 35, AMMCreate,
Delegation::delegatable,
featureAMM,
createPseudoAcct,
({
{sfAmount, soeREQUIRED},
{sfAmount2, soeREQUIRED},
@@ -442,13 +332,9 @@ TRANSACTION(ttAMM_CREATE, 35, AMMCreate,
}))
/** This transaction type deposits into an AMM instance */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/AMMDeposit.h>
#endif
TRANSACTION(ttAMM_DEPOSIT, 36, AMMDeposit,
Delegation::delegatable,
featureAMM,
noPriv,
({
{sfAsset, soeREQUIRED},
{sfAsset2, soeREQUIRED},
@@ -460,13 +346,9 @@ TRANSACTION(ttAMM_DEPOSIT, 36, AMMDeposit,
}))
/** This transaction type withdraws from an AMM instance */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/AMMWithdraw.h>
#endif
TRANSACTION(ttAMM_WITHDRAW, 37, AMMWithdraw,
Delegation::delegatable,
featureAMM,
mayDeleteAcct,
({
{sfAsset, soeREQUIRED},
{sfAsset2, soeREQUIRED},
@@ -477,13 +359,9 @@ TRANSACTION(ttAMM_WITHDRAW, 37, AMMWithdraw,
}))
/** This transaction type votes for the trading fee */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/AMMVote.h>
#endif
TRANSACTION(ttAMM_VOTE, 38, AMMVote,
Delegation::delegatable,
featureAMM,
noPriv,
({
{sfAsset, soeREQUIRED},
{sfAsset2, soeREQUIRED},
@@ -491,13 +369,9 @@ TRANSACTION(ttAMM_VOTE, 38, AMMVote,
}))
/** This transaction type bids for the auction slot */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/AMMBid.h>
#endif
TRANSACTION(ttAMM_BID, 39, AMMBid,
Delegation::delegatable,
featureAMM,
noPriv,
({
{sfAsset, soeREQUIRED},
{sfAsset2, soeREQUIRED},
@@ -507,26 +381,18 @@ TRANSACTION(ttAMM_BID, 39, AMMBid,
}))
/** This transaction type deletes AMM in the empty state */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/AMMDelete.h>
#endif
TRANSACTION(ttAMM_DELETE, 40, AMMDelete,
Delegation::delegatable,
featureAMM,
mustDeleteAcct,
({
{sfAsset, soeREQUIRED},
{sfAsset2, soeREQUIRED},
}))
/** This transactions creates a crosschain sequence number */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/XChainBridge.h>
#endif
TRANSACTION(ttXCHAIN_CREATE_CLAIM_ID, 41, XChainCreateClaimID,
Delegation::delegatable,
featureXChainBridge,
noPriv,
({
{sfXChainBridge, soeREQUIRED},
{sfSignatureReward, soeREQUIRED},
@@ -537,7 +403,6 @@ TRANSACTION(ttXCHAIN_CREATE_CLAIM_ID, 41, XChainCreateClaimID,
TRANSACTION(ttXCHAIN_COMMIT, 42, XChainCommit,
Delegation::delegatable,
featureXChainBridge,
noPriv,
({
{sfXChainBridge, soeREQUIRED},
{sfXChainClaimID, soeREQUIRED},
@@ -549,7 +414,6 @@ TRANSACTION(ttXCHAIN_COMMIT, 42, XChainCommit,
TRANSACTION(ttXCHAIN_CLAIM, 43, XChainClaim,
Delegation::delegatable,
featureXChainBridge,
noPriv,
({
{sfXChainBridge, soeREQUIRED},
{sfXChainClaimID, soeREQUIRED},
@@ -562,7 +426,6 @@ TRANSACTION(ttXCHAIN_CLAIM, 43, XChainClaim,
TRANSACTION(ttXCHAIN_ACCOUNT_CREATE_COMMIT, 44, XChainAccountCreateCommit,
Delegation::delegatable,
featureXChainBridge,
noPriv,
({
{sfXChainBridge, soeREQUIRED},
{sfDestination, soeREQUIRED},
@@ -574,7 +437,6 @@ TRANSACTION(ttXCHAIN_ACCOUNT_CREATE_COMMIT, 44, XChainAccountCreateCommit,
TRANSACTION(ttXCHAIN_ADD_CLAIM_ATTESTATION, 45, XChainAddClaimAttestation,
Delegation::delegatable,
featureXChainBridge,
createAcct,
({
{sfXChainBridge, soeREQUIRED},
@@ -591,11 +453,9 @@ TRANSACTION(ttXCHAIN_ADD_CLAIM_ATTESTATION, 45, XChainAddClaimAttestation,
}))
/** This transaction adds an attestation to an account */
TRANSACTION(ttXCHAIN_ADD_ACCOUNT_CREATE_ATTESTATION, 46,
XChainAddAccountCreateAttestation,
TRANSACTION(ttXCHAIN_ADD_ACCOUNT_CREATE_ATTESTATION, 46, XChainAddAccountCreateAttestation,
Delegation::delegatable,
featureXChainBridge,
createAcct,
({
{sfXChainBridge, soeREQUIRED},
@@ -616,7 +476,6 @@ TRANSACTION(ttXCHAIN_ADD_ACCOUNT_CREATE_ATTESTATION, 46,
TRANSACTION(ttXCHAIN_MODIFY_BRIDGE, 47, XChainModifyBridge,
Delegation::delegatable,
featureXChainBridge,
noPriv,
({
{sfXChainBridge, soeREQUIRED},
{sfSignatureReward, soeOPTIONAL},
@@ -627,7 +486,6 @@ TRANSACTION(ttXCHAIN_MODIFY_BRIDGE, 47, XChainModifyBridge,
TRANSACTION(ttXCHAIN_CREATE_BRIDGE, 48, XChainCreateBridge,
Delegation::delegatable,
featureXChainBridge,
noPriv,
({
{sfXChainBridge, soeREQUIRED},
{sfSignatureReward, soeREQUIRED},
@@ -635,13 +493,9 @@ TRANSACTION(ttXCHAIN_CREATE_BRIDGE, 48, XChainCreateBridge,
}))
/** This transaction type creates or updates a DID */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/DID.h>
#endif
TRANSACTION(ttDID_SET, 49, DIDSet,
Delegation::delegatable,
featureDID,
noPriv,
({
{sfDIDDocument, soeOPTIONAL},
{sfURI, soeOPTIONAL},
@@ -652,17 +506,12 @@ TRANSACTION(ttDID_SET, 49, DIDSet,
TRANSACTION(ttDID_DELETE, 50, DIDDelete,
Delegation::delegatable,
featureDID,
noPriv,
({}))
/** This transaction type creates an Oracle instance */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/SetOracle.h>
#endif
TRANSACTION(ttORACLE_SET, 51, OracleSet,
Delegation::delegatable,
featurePriceOracle,
noPriv,
({
{sfOracleDocumentID, soeREQUIRED},
{sfProvider, soeOPTIONAL},
@@ -673,98 +522,65 @@ TRANSACTION(ttORACLE_SET, 51, OracleSet,
}))
/** This transaction type deletes an Oracle instance */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/DeleteOracle.h>
#endif
TRANSACTION(ttORACLE_DELETE, 52, OracleDelete,
Delegation::delegatable,
featurePriceOracle,
noPriv,
({
{sfOracleDocumentID, soeREQUIRED},
}))
/** This transaction type fixes a problem in the ledger state */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/LedgerStateFix.h>
#endif
TRANSACTION(ttLEDGER_STATE_FIX, 53, LedgerStateFix,
Delegation::delegatable,
fixNFTokenPageLinks,
noPriv,
({
{sfLedgerFixType, soeREQUIRED},
{sfOwner, soeOPTIONAL},
}))
/** This transaction type creates a MPTokensIssuance instance */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/MPTokenIssuanceCreate.h>
#endif
TRANSACTION(ttMPTOKEN_ISSUANCE_CREATE, 54, MPTokenIssuanceCreate,
Delegation::delegatable,
featureMPTokensV1,
createMPTIssuance,
({
{sfAssetScale, soeOPTIONAL},
{sfTransferFee, soeOPTIONAL},
{sfMaximumAmount, soeOPTIONAL},
{sfMPTokenMetadata, soeOPTIONAL},
{sfDomainID, soeOPTIONAL},
{sfMutableFlags, soeOPTIONAL},
}))
/** This transaction type destroys a MPTokensIssuance instance */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/MPTokenIssuanceDestroy.h>
#endif
TRANSACTION(ttMPTOKEN_ISSUANCE_DESTROY, 55, MPTokenIssuanceDestroy,
Delegation::delegatable,
featureMPTokensV1,
destroyMPTIssuance,
({
{sfMPTokenIssuanceID, soeREQUIRED},
}))
/** This transaction type sets flags on a MPTokensIssuance or MPToken instance */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/MPTokenIssuanceSet.h>
#endif
TRANSACTION(ttMPTOKEN_ISSUANCE_SET, 56, MPTokenIssuanceSet,
Delegation::delegatable,
featureMPTokensV1,
noPriv,
({
{sfMPTokenIssuanceID, soeREQUIRED},
{sfHolder, soeOPTIONAL},
{sfDomainID, soeOPTIONAL},
{sfMPTokenMetadata, soeOPTIONAL},
{sfTransferFee, soeOPTIONAL},
{sfMutableFlags, soeOPTIONAL},
{sfIssuerElGamalPublicKey, soeOPTIONAL},
}))
/** This transaction type authorizes a MPToken instance */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/MPTokenAuthorize.h>
#endif
TRANSACTION(ttMPTOKEN_AUTHORIZE, 57, MPTokenAuthorize,
Delegation::delegatable,
featureMPTokensV1,
mustAuthorizeMPT,
({
{sfMPTokenIssuanceID, soeREQUIRED},
{sfHolder, soeOPTIONAL},
}))
/** This transaction type create an Credential instance */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/Credentials.h>
#endif
TRANSACTION(ttCREDENTIAL_CREATE, 58, CredentialCreate,
Delegation::delegatable,
featureCredentials,
noPriv,
({
{sfSubject, soeREQUIRED},
{sfCredentialType, soeREQUIRED},
@@ -776,7 +592,6 @@ TRANSACTION(ttCREDENTIAL_CREATE, 58, CredentialCreate,
TRANSACTION(ttCREDENTIAL_ACCEPT, 59, CredentialAccept,
Delegation::delegatable,
featureCredentials,
noPriv,
({
{sfIssuer, soeREQUIRED},
{sfCredentialType, soeREQUIRED},
@@ -786,7 +601,6 @@ TRANSACTION(ttCREDENTIAL_ACCEPT, 59, CredentialAccept,
TRANSACTION(ttCREDENTIAL_DELETE, 60, CredentialDelete,
Delegation::delegatable,
featureCredentials,
noPriv,
({
{sfSubject, soeOPTIONAL},
{sfIssuer, soeOPTIONAL},
@@ -794,13 +608,9 @@ TRANSACTION(ttCREDENTIAL_DELETE, 60, CredentialDelete,
}))
/** This transaction type modify a NFToken */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/NFTokenModify.h>
#endif
TRANSACTION(ttNFTOKEN_MODIFY, 61, NFTokenModify,
Delegation::delegatable,
featureDynamicNFT,
noPriv,
({
{sfNFTokenID, soeREQUIRED},
{sfOwner, soeOPTIONAL},
@@ -808,51 +618,35 @@ TRANSACTION(ttNFTOKEN_MODIFY, 61, NFTokenModify,
}))
/** This transaction type creates or modifies a Permissioned Domain */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/PermissionedDomainSet.h>
#endif
TRANSACTION(ttPERMISSIONED_DOMAIN_SET, 62, PermissionedDomainSet,
Delegation::delegatable,
featurePermissionedDomains,
noPriv,
({
{sfDomainID, soeOPTIONAL},
{sfAcceptedCredentials, soeREQUIRED},
}))
/** This transaction type deletes a Permissioned Domain */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/PermissionedDomainDelete.h>
#endif
TRANSACTION(ttPERMISSIONED_DOMAIN_DELETE, 63, PermissionedDomainDelete,
Delegation::delegatable,
featurePermissionedDomains,
noPriv,
({
{sfDomainID, soeREQUIRED},
}))
/** This transaction type delegates authorized account specified permissions */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/DelegateSet.h>
#endif
TRANSACTION(ttDELEGATE_SET, 64, DelegateSet,
Delegation::notDelegatable,
featurePermissionDelegationV1_1,
noPriv,
featurePermissionDelegation,
({
{sfAuthorize, soeREQUIRED},
{sfPermissions, soeREQUIRED},
}))
/** This transaction creates a single asset vault. */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/VaultCreate.h>
#endif
TRANSACTION(ttVAULT_CREATE, 65, VaultCreate,
Delegation::delegatable,
featureSingleAssetVault,
createPseudoAcct | createMPTIssuance | mustModifyVault,
({
{sfAsset, soeREQUIRED, soeMPTSupported},
{sfAssetsMaximum, soeOPTIONAL},
@@ -864,13 +658,9 @@ TRANSACTION(ttVAULT_CREATE, 65, VaultCreate,
}))
/** This transaction updates a single asset vault. */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/VaultSet.h>
#endif
TRANSACTION(ttVAULT_SET, 66, VaultSet,
Delegation::delegatable,
featureSingleAssetVault,
mustModifyVault,
({
{sfVaultID, soeREQUIRED},
{sfAssetsMaximum, soeOPTIONAL},
@@ -879,38 +669,26 @@ TRANSACTION(ttVAULT_SET, 66, VaultSet,
}))
/** This transaction deletes a single asset vault. */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/VaultDelete.h>
#endif
TRANSACTION(ttVAULT_DELETE, 67, VaultDelete,
Delegation::delegatable,
featureSingleAssetVault,
mustDeleteAcct | destroyMPTIssuance | mustModifyVault,
({
{sfVaultID, soeREQUIRED},
}))
/** This transaction trades assets for shares with a vault. */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/VaultDeposit.h>
#endif
TRANSACTION(ttVAULT_DEPOSIT, 68, VaultDeposit,
Delegation::delegatable,
featureSingleAssetVault,
mayAuthorizeMPT | mustModifyVault,
({
{sfVaultID, soeREQUIRED},
{sfAmount, soeREQUIRED, soeMPTSupported},
}))
/** This transaction trades shares for assets with a vault. */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/VaultWithdraw.h>
#endif
TRANSACTION(ttVAULT_WITHDRAW, 69, VaultWithdraw,
Delegation::delegatable,
featureSingleAssetVault,
mayDeleteMPT | mayAuthorizeMPT | mustModifyVault,
({
{sfVaultID, soeREQUIRED},
{sfAmount, soeREQUIRED, soeMPTSupported},
@@ -919,13 +697,9 @@ TRANSACTION(ttVAULT_WITHDRAW, 69, VaultWithdraw,
}))
/** This transaction claws back tokens from a vault. */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/VaultClawback.h>
#endif
TRANSACTION(ttVAULT_CLAWBACK, 70, VaultClawback,
Delegation::delegatable,
featureSingleAssetVault,
mayDeleteMPT | mustModifyVault,
({
{sfVaultID, soeREQUIRED},
{sfHolder, soeREQUIRED},
@@ -933,105 +707,21 @@ TRANSACTION(ttVAULT_CLAWBACK, 70, VaultClawback,
}))
/** This transaction type batches together transactions. */
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/Batch.h>
#endif
TRANSACTION(ttBATCH, 71, Batch,
Delegation::notDelegatable,
featureBatch,
noPriv,
({
{sfRawTransactions, soeREQUIRED},
{sfBatchSigners, soeOPTIONAL},
}))
/** This transaction type converts into confidential MPT balance. */
#if TRANSACTION_INCLUDE
#include <xrpld/app/tx/detail/ConfidentialConvert.h>
#endif
TRANSACTION(ttCONFIDENTIAL_CONVERT, 72, ConfidentialConvert,
Delegation::delegatable,
featureConfidentialTransfer,
noPriv,
({
{sfMPTokenIssuanceID, soeREQUIRED},
{sfMPTAmount, soeREQUIRED},
{sfHolderElGamalPublicKey, soeOPTIONAL},
{sfHolderEncryptedAmount, soeREQUIRED},
{sfIssuerEncryptedAmount, soeREQUIRED},
{sfZKProof, soeREQUIRED},
}))
/** This transaction type merges MPT inbox. */
#if TRANSACTION_INCLUDE
#include <xrpld/app/tx/detail/ConfidentialMergeInbox.h>
#endif
TRANSACTION(ttCONFIDENTIAL_MERGE_INBOX, 73, ConfidentialMergeInbox,
Delegation::delegatable,
featureConfidentialTransfer,
noPriv,
({
{sfMPTokenIssuanceID, soeREQUIRED},
}))
/** This transaction type converts back into public MPT balance. */
#if TRANSACTION_INCLUDE
#include <xrpld/app/tx/detail/ConfidentialConvertBack.h>
#endif
TRANSACTION(ttCONFIDENTIAL_CONVERT_BACK, 74, ConfidentialConvertBack,
Delegation::delegatable,
featureConfidentialTransfer,
noPriv,
({
{sfMPTokenIssuanceID, soeREQUIRED},
{sfMPTAmount, soeREQUIRED},
{sfHolderEncryptedAmount, soeREQUIRED},
{sfIssuerEncryptedAmount, soeREQUIRED},
{sfZKProof, soeREQUIRED},
}))
#if TRANSACTION_INCLUDE
#include <xrpld/app/tx/detail/ConfidentialSend.h>
#endif
TRANSACTION(ttCONFIDENTIAL_SEND, 75, ConfidentialSend,
Delegation::delegatable,
featureConfidentialTransfer,
noPriv,
({
{sfMPTokenIssuanceID, soeREQUIRED},
{sfDestination, soeREQUIRED},
{sfSenderEncryptedAmount, soeREQUIRED},
{sfDestinationEncryptedAmount, soeREQUIRED},
{sfIssuerEncryptedAmount, soeREQUIRED},
{sfZKProof, soeREQUIRED},
{sfCredentialIDs, soeOPTIONAL},
}))
#if TRANSACTION_INCLUDE
#include <xrpld/app/tx/detail/ConfidentialClawback.h>
#endif
TRANSACTION(ttCONFIDENTIAL_CLAWBACK, 76, ConfidentialClawback,
Delegation::delegatable,
featureConfidentialTransfer,
noPriv,
({
{sfMPTokenIssuanceID, soeREQUIRED},
{sfHolder, soeREQUIRED},
{sfMPTAmount, soeREQUIRED},
{sfZKProof, soeREQUIRED},
}))
/** This system-generated transaction type is used to update the status of the various amendments.
For details, see: https://xrpl.org/amendments.html
*/
#if TRANSACTION_INCLUDE
# include <xrpld/app/tx/detail/Change.h>
#endif
TRANSACTION(ttAMENDMENT, 100, EnableAmendment,
Delegation::notDelegatable,
uint256{},
noPriv,
({
{sfLedgerSequence, soeREQUIRED},
{sfAmendment, soeREQUIRED},
@@ -1043,7 +733,6 @@ TRANSACTION(ttAMENDMENT, 100, EnableAmendment,
TRANSACTION(ttFEE, 101, SetFee,
Delegation::notDelegatable,
uint256{},
noPriv,
({
{sfLedgerSequence, soeOPTIONAL},
// Old version uses raw numbers
@@ -1064,7 +753,6 @@ TRANSACTION(ttFEE, 101, SetFee,
TRANSACTION(ttUNL_MODIFY, 102, UNLModify,
Delegation::notDelegatable,
uint256{},
noPriv,
({
{sfUNLModifyDisabling, soeREQUIRED},
{sfLedgerSequence, soeREQUIRED},

View File

@@ -569,7 +569,6 @@ JSS(settle_delay); // out: AccountChannels
JSS(severity); // in: LogLevel
JSS(shares); // out: VaultInfo
JSS(signature); // out: NetworkOPs, ChannelAuthorize
JSS(signature_target); // in: TransactionSign
JSS(signature_verified); // out: ChannelVerify
JSS(signing_key); // out: NetworkOPs
JSS(signing_keys); // out: ValidatorList
@@ -723,11 +722,11 @@ JSS(write_load); // out: GetCounts
#pragma push_macro("LEDGER_ENTRY_DUPLICATE")
#undef LEDGER_ENTRY_DUPLICATE
#define LEDGER_ENTRY(tag, value, name, rpcName, ...) \
JSS(name); \
#define LEDGER_ENTRY(tag, value, name, rpcName, fields) \
JSS(name); \
JSS(rpcName);
#define LEDGER_ENTRY_DUPLICATE(tag, value, name, rpcName, ...) JSS(rpcName);
#define LEDGER_ENTRY_DUPLICATE(tag, value, name, rpcName, fields) JSS(rpcName);
#include <xrpl/protocol/detail/ledger_entries.macro>

View File

@@ -21,7 +21,6 @@
#define RIPPLE_RESOURCE_CONSUMER_H_INCLUDED
#include <xrpl/basics/Log.h>
#include <xrpl/protocol/PublicKey.h>
#include <xrpl/resource/Charge.h>
#include <xrpl/resource/Disposition.h>
@@ -88,9 +87,6 @@ public:
Entry&
entry();
void
setPublicKey(PublicKey const& publicKey);
private:
Logic* m_logic;
Entry* m_entry;

View File

@@ -53,7 +53,7 @@ struct Entry : public beast::List<Entry>::Node
std::string
to_string() const
{
return getFingerprint(key->address, publicKey);
return key->address.to_string();
}
/**
@@ -82,9 +82,6 @@ struct Entry : public beast::List<Entry>::Node
return local_balance.add(charge, now) + remote_balance;
}
// The public key of the peer
std::optional<PublicKey> publicKey;
// Back pointer to the map key (bit of a hack here)
Key const* key;

View File

@@ -436,12 +436,10 @@ public:
admin_.erase(admin_.iterator_to(entry));
break;
default:
// LCOV_EXCL_START
UNREACHABLE(
"ripple::Resource::Logic::release : invalid entry "
"kind");
break;
// LCOV_EXCL_STOP
}
inactive_.push_back(entry);
entry.whenExpires = m_clock.now() + secondsUntilExpiration;

View File

@@ -30,29 +30,15 @@
#include <boost/asio/buffer.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/post.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/beast/core/detect_ssl.hpp>
#include <boost/beast/core/multi_buffer.hpp>
#include <boost/beast/core/tcp_stream.hpp>
#include <boost/container/flat_map.hpp>
#include <boost/predef.h>
#if !BOOST_OS_WINDOWS
#include <sys/resource.h>
#include <dirent.h>
#include <unistd.h>
#endif
#include <algorithm>
#include <chrono>
#include <cstdint>
#include <functional>
#include <memory>
#include <optional>
#include <sstream>
namespace ripple {
@@ -112,27 +98,10 @@ private:
boost::asio::strand<boost::asio::io_context::executor_type> strand_;
bool ssl_;
bool plain_;
static constexpr std::chrono::milliseconds INITIAL_ACCEPT_DELAY{50};
static constexpr std::chrono::milliseconds MAX_ACCEPT_DELAY{2000};
std::chrono::milliseconds accept_delay_{INITIAL_ACCEPT_DELAY};
boost::asio::steady_timer backoff_timer_;
static constexpr double FREE_FD_THRESHOLD = 0.70;
struct FDStats
{
std::uint64_t used{0};
std::uint64_t limit{0};
};
void
reOpen();
std::optional<FDStats>
query_fd_stats() const;
bool
should_throttle_for_fds();
public:
Door(
Handler& handler,
@@ -330,7 +299,6 @@ Door<Handler>::Door(
, plain_(
port_.protocol.count("http") > 0 || port_.protocol.count("ws") > 0 ||
port_.protocol.count("ws2"))
, backoff_timer_(io_context)
{
reOpen();
}
@@ -355,7 +323,6 @@ Door<Handler>::close()
return boost::asio::post(
strand_,
std::bind(&Door<Handler>::close, this->shared_from_this()));
backoff_timer_.cancel();
error_code ec;
acceptor_.close(ec);
}
@@ -401,17 +368,6 @@ Door<Handler>::do_accept(boost::asio::yield_context do_yield)
{
while (acceptor_.is_open())
{
if (should_throttle_for_fds())
{
backoff_timer_.expires_after(accept_delay_);
boost::system::error_code tec;
backoff_timer_.async_wait(do_yield[tec]);
accept_delay_ = std::min(accept_delay_ * 2, MAX_ACCEPT_DELAY);
JLOG(j_.warn()) << "Throttling do_accept for "
<< accept_delay_.count() << "ms.";
continue;
}
error_code ec;
endpoint_type remote_address;
stream_type stream(ioc_);
@@ -421,28 +377,15 @@ Door<Handler>::do_accept(boost::asio::yield_context do_yield)
{
if (ec == boost::asio::error::operation_aborted)
break;
if (ec == boost::asio::error::no_descriptors ||
ec == boost::asio::error::no_buffer_space)
JLOG(j_.error()) << "accept: " << ec.message();
if (ec == boost::asio::error::no_descriptors)
{
JLOG(j_.warn()) << "accept: Too many open files. Pausing for "
<< accept_delay_.count() << "ms.";
backoff_timer_.expires_after(accept_delay_);
boost::system::error_code tec;
backoff_timer_.async_wait(do_yield[tec]);
accept_delay_ = std::min(accept_delay_ * 2, MAX_ACCEPT_DELAY);
}
else
{
JLOG(j_.error()) << "accept error: " << ec.message();
JLOG(j_.info()) << "re-opening acceptor";
reOpen();
}
continue;
}
accept_delay_ = INITIAL_ACCEPT_DELAY;
if (ssl_ && plain_)
{
if (auto sp = ios().template emplace<Detector>(
@@ -465,60 +408,6 @@ Door<Handler>::do_accept(boost::asio::yield_context do_yield)
}
}
template <class Handler>
std::optional<typename Door<Handler>::FDStats>
Door<Handler>::query_fd_stats() const
{
#if BOOST_OS_WINDOWS
return std::nullopt;
#else
FDStats s;
struct rlimit rl;
if (getrlimit(RLIMIT_NOFILE, &rl) != 0 || rl.rlim_cur == RLIM_INFINITY)
return std::nullopt;
s.limit = static_cast<std::uint64_t>(rl.rlim_cur);
#if BOOST_OS_LINUX
constexpr char const* kFdDir = "/proc/self/fd";
#else
constexpr char const* kFdDir = "/dev/fd";
#endif
if (DIR* d = ::opendir(kFdDir))
{
std::uint64_t cnt = 0;
while (::readdir(d) != nullptr)
++cnt;
::closedir(d);
// readdir counts '.', '..', and the DIR* itself shows in the list
s.used = (cnt >= 3) ? (cnt - 3) : 0;
return s;
}
return std::nullopt;
#endif
}
template <class Handler>
bool
Door<Handler>::should_throttle_for_fds()
{
#if BOOST_OS_WINDOWS
return false;
#else
auto const stats = query_fd_stats();
if (!stats || stats->limit == 0)
return false;
auto const& s = *stats;
auto const free = (s.limit > s.used) ? (s.limit - s.used) : 0ull;
double const free_ratio =
static_cast<double>(free) / static_cast<double>(s.limit);
if (free_ratio < FREE_FD_THRESHOLD)
{
return true;
}
return false;
#endif
}
} // namespace ripple
#endif

View File

@@ -239,11 +239,9 @@ Logs::fromSeverity(beast::severities::Severity level)
case kError:
return lsERROR;
// LCOV_EXCL_START
default:
UNREACHABLE("ripple::Logs::fromSeverity : invalid severity");
[[fallthrough]];
// LCOV_EXCL_STOP
case kFatal:
break;
}
@@ -267,11 +265,9 @@ Logs::toSeverity(LogSeverity level)
return kWarning;
case lsERROR:
return kError;
// LCOV_EXCL_START
default:
UNREACHABLE("ripple::Logs::toSeverity : invalid severity");
[[fallthrough]];
// LCOV_EXCL_STOP
case lsFATAL:
break;
}
@@ -296,11 +292,9 @@ Logs::toString(LogSeverity s)
return "Error";
case lsFATAL:
return "Fatal";
// LCOV_EXCL_START
default:
UNREACHABLE("ripple::Logs::toString : invalid severity");
return "Unknown";
// LCOV_EXCL_STOP
}
}
@@ -362,11 +356,9 @@ Logs::format(
case kError:
output += "ERR ";
break;
// LCOV_EXCL_START
default:
UNREACHABLE("ripple::Logs::format : invalid severity");
[[fallthrough]];
// LCOV_EXCL_STOP
case kFatal:
output += "FTL ";
break;

View File

@@ -36,7 +36,6 @@ LogThrow(std::string const& title)
[[noreturn]] void
LogicError(std::string const& s) noexcept
{
// LCOV_EXCL_START
JLOG(debugLog().fatal()) << s;
std::cerr << "Logic error: " << s << std::endl;
// Use a non-standard contract naming here (without namespace) because
@@ -46,7 +45,6 @@ LogicError(std::string const& s) noexcept
// For the above reasons, we want this contract to stand out.
UNREACHABLE("LogicError", {{"message", s}});
std::abort();
// LCOV_EXCL_STOP
}
} // namespace ripple

View File

@@ -174,7 +174,7 @@ Array::append(Json::Value const& v)
return;
}
}
UNREACHABLE("Json::Array::append : invalid type"); // LCOV_EXCL_LINE
UNREACHABLE("Json::Array::append : invalid type");
}
void
@@ -209,7 +209,7 @@ Object::set(std::string const& k, Json::Value const& v)
return;
}
}
UNREACHABLE("Json::Object::set : invalid type"); // LCOV_EXCL_LINE
UNREACHABLE("Json::Object::set : invalid type");
}
//------------------------------------------------------------------------------

View File

@@ -213,10 +213,8 @@ Value::Value(ValueType type) : type_(type), allocated_(0)
value_.bool_ = false;
break;
// LCOV_EXCL_START
default:
UNREACHABLE("Json::Value::Value(ValueType) : invalid type");
// LCOV_EXCL_STOP
}
}
@@ -292,10 +290,8 @@ Value::Value(Value const& other) : type_(other.type_)
value_.map_ = new ObjectValues(*other.value_.map_);
break;
// LCOV_EXCL_START
default:
UNREACHABLE("Json::Value::Value(Value const&) : invalid type");
// LCOV_EXCL_STOP
}
}
@@ -322,10 +318,8 @@ Value::~Value()
delete value_.map_;
break;
// LCOV_EXCL_START
default:
UNREACHABLE("Json::Value::~Value : invalid type");
// LCOV_EXCL_STOP
}
}
@@ -425,10 +419,8 @@ operator<(Value const& x, Value const& y)
return *x.value_.map_ < *y.value_.map_;
}
// LCOV_EXCL_START
default:
UNREACHABLE("Json::operator<(Value, Value) : invalid type");
// LCOV_EXCL_STOP
}
return 0; // unreachable
@@ -473,10 +465,8 @@ operator==(Value const& x, Value const& y)
return x.value_.map_->size() == y.value_.map_->size() &&
*x.value_.map_ == *y.value_.map_;
// LCOV_EXCL_START
default:
UNREACHABLE("Json::operator==(Value, Value) : invalid type");
// LCOV_EXCL_STOP
}
return 0; // unreachable
@@ -516,10 +506,8 @@ Value::asString() const
case objectValue:
JSON_ASSERT_MESSAGE(false, "Type is not convertible to string");
// LCOV_EXCL_START
default:
UNREACHABLE("Json::Value::asString : invalid type");
// LCOV_EXCL_STOP
}
return ""; // unreachable
@@ -560,10 +548,8 @@ Value::asInt() const
case objectValue:
JSON_ASSERT_MESSAGE(false, "Type is not convertible to int");
// LCOV_EXCL_START
default:
UNREACHABLE("Json::Value::asInt : invalid type");
// LCOV_EXCL_STOP
}
return 0; // unreachable;
@@ -604,10 +590,8 @@ Value::asUInt() const
case objectValue:
JSON_ASSERT_MESSAGE(false, "Type is not convertible to uint");
// LCOV_EXCL_START
default:
UNREACHABLE("Json::Value::asUInt : invalid type");
// LCOV_EXCL_STOP
}
return 0; // unreachable;
@@ -638,10 +622,8 @@ Value::asDouble() const
case objectValue:
JSON_ASSERT_MESSAGE(false, "Type is not convertible to double");
// LCOV_EXCL_START
default:
UNREACHABLE("Json::Value::asDouble : invalid type");
// LCOV_EXCL_STOP
}
return 0; // unreachable;
@@ -672,10 +654,8 @@ Value::asBool() const
case objectValue:
return value_.map_->size() != 0;
// LCOV_EXCL_START
default:
UNREACHABLE("Json::Value::asBool : invalid type");
// LCOV_EXCL_STOP
}
return false; // unreachable;
@@ -730,10 +710,8 @@ Value::isConvertibleTo(ValueType other) const
return other == objectValue ||
(other == nullValue && value_.map_->size() == 0);
// LCOV_EXCL_START
default:
UNREACHABLE("Json::Value::isConvertible : invalid type");
// LCOV_EXCL_STOP
}
return false; // unreachable;
@@ -766,10 +744,8 @@ Value::size() const
case objectValue:
return Int(value_.map_->size());
// LCOV_EXCL_START
default:
UNREACHABLE("Json::Value::size : invalid type");
// LCOV_EXCL_STOP
}
return 0; // unreachable;

View File

@@ -383,7 +383,7 @@ public:
static boost::regex reStatus{
"\\`HTTP/1\\S+ (\\d{3}) .*\\'"}; // HTTP/1.1 200 OK
static boost::regex reSize{
"\\`.*\\r\\nContent-Length:\\s+([0-9]+).*\\'", boost::regex::icase};
"\\`.*\\r\\nContent-Length:\\s+([0-9]+).*\\'"};
static boost::regex reBody{"\\`.*\\r\\n\\r\\n(.*)\\'"};
boost::smatch smMatch;

View File

@@ -36,7 +36,7 @@ namespace BuildInfo {
// and follow the format described at http://semver.org/
//------------------------------------------------------------------------------
// clang-format off
char const* const versionString = "3.0.0-b1"
char const* const versionString = "2.6.0"
// clang-format on
#if defined(DEBUG) || defined(SANITIZER)

View File

@@ -1,607 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2025 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include <xrpl/protocol/ConfidentialTransfer.h>
#include <xrpl/protocol/Protocol.h>
#include <xrpl/protocol/TER.h>
#include <openssl/rand.h>
#include <openssl/sha.h>
namespace ripple {
int
secp256k1_elgamal_generate_keypair(
secp256k1_context const* ctx,
unsigned char* privkey,
secp256k1_pubkey* pubkey)
{
// 1. Generate 32 random bytes for the private key
do
{
if (RAND_bytes(privkey, 32) != 1)
{
return 0; // Failure
}
// 2. Verify the random data is a valid private key.
} while (secp256k1_ec_seckey_verify(ctx, privkey) != 1);
// 3. Create the corresponding public key.
if (secp256k1_ec_pubkey_create(ctx, pubkey, privkey) != 1)
{
return 0; // Failure
}
return 1; // Success
}
// ... implementation of secp256k1_elgamal_encrypt ...
int
secp256k1_elgamal_encrypt(
secp256k1_context const* ctx,
secp256k1_pubkey* c1,
secp256k1_pubkey* c2,
secp256k1_pubkey const* pubkey_Q,
uint64_t amount,
unsigned char const* blinding_factor)
{
secp256k1_pubkey S;
// First, calculate C1 = k * G
if (secp256k1_ec_pubkey_create(ctx, c1, blinding_factor) != 1)
{
return 0;
}
// Next, calculate the shared secret S = k * Q
S = *pubkey_Q;
if (secp256k1_ec_pubkey_tweak_mul(ctx, &S, blinding_factor) != 1)
{
return 0;
}
// --- Handle the amount ---
if (amount == 0)
{
// For amount = 0, C2 = S.
*c2 = S;
}
else
{
// For non-zero amounts, proceed as before.
unsigned char amount_scalar[32] = {0};
secp256k1_pubkey M;
secp256k1_pubkey const* points_to_add[2];
// Convert amount to a 32-byte BIG-ENDIAN scalar.
for (int i = 0; i < 8; ++i)
{
amount_scalar[31 - i] = (amount >> (i * 8)) & 0xFF;
}
// Calculate M = amount * G
if (secp256k1_ec_pubkey_create(ctx, &M, amount_scalar) != 1)
{
return 0;
}
// Calculate C2 = M + S
points_to_add[0] = &M;
points_to_add[1] = &S;
if (secp256k1_ec_pubkey_combine(ctx, c2, points_to_add, 2) != 1)
{
return 0;
}
}
return 1; // Success
}
// ... implementation of secp256k1_elgamal_decrypt ...
int
secp256k1_elgamal_decrypt(
secp256k1_context const* ctx,
uint64_t* amount,
secp256k1_pubkey const* c1,
secp256k1_pubkey const* c2,
unsigned char const* privkey)
{
secp256k1_pubkey S, M, G_point, current_M, next_M;
secp256k1_pubkey const* points_to_add[2];
unsigned char c2_bytes[33], s_bytes[33], m_bytes[33], current_m_bytes[33];
size_t len;
uint64_t i;
/* Create the scalar '1' in big-endian format */
unsigned char one_scalar[32] = {0};
one_scalar[31] = 1;
/* --- Executable Code --- */
// 1. Calculate S = privkey * C1
S = *c1;
if (secp256k1_ec_pubkey_tweak_mul(ctx, &S, privkey) != 1)
{
return 0;
}
// 2. Check for amount = 0 by comparing serialized points
len = sizeof(c2_bytes);
if (secp256k1_ec_pubkey_serialize(
ctx, c2_bytes, &len, c2, SECP256K1_EC_COMPRESSED) != 1)
return 0;
len = sizeof(s_bytes);
if (secp256k1_ec_pubkey_serialize(
ctx, s_bytes, &len, &S, SECP256K1_EC_COMPRESSED) != 1)
return 0;
if (memcmp(c2_bytes, s_bytes, sizeof(c2_bytes)) == 0)
{
*amount = 0;
return 1;
}
// 3. Recover M = C2 - S
if (secp256k1_ec_pubkey_negate(ctx, &S) != 1)
return 0;
points_to_add[0] = c2;
points_to_add[1] = &S;
if (secp256k1_ec_pubkey_combine(ctx, &M, points_to_add, 2) != 1)
{
return 0;
}
// 4. Serialize M once for comparison in the loop
len = sizeof(m_bytes);
if (secp256k1_ec_pubkey_serialize(
ctx, m_bytes, &len, &M, SECP256K1_EC_COMPRESSED) != 1)
return 0;
// 5. Brute-force search loop
if (secp256k1_ec_pubkey_create(ctx, &G_point, one_scalar) != 1)
return 0;
current_M = G_point;
for (i = 1; i <= 1000000; ++i)
{
len = sizeof(current_m_bytes);
if (secp256k1_ec_pubkey_serialize(
ctx,
current_m_bytes,
&len,
&current_M,
SECP256K1_EC_COMPRESSED) != 1)
return 0;
if (memcmp(m_bytes, current_m_bytes, sizeof(m_bytes)) == 0)
{
*amount = i;
return 1;
}
points_to_add[0] = &current_M;
points_to_add[1] = &G_point;
if (secp256k1_ec_pubkey_combine(ctx, &next_M, points_to_add, 2) != 1)
return 0;
current_M = next_M;
}
return 0; // Not found
}
int
secp256k1_elgamal_add(
secp256k1_context const* ctx,
secp256k1_pubkey* sum_c1,
secp256k1_pubkey* sum_c2,
secp256k1_pubkey const* a_c1,
secp256k1_pubkey const* a_c2,
secp256k1_pubkey const* b_c1,
secp256k1_pubkey const* b_c2)
{
secp256k1_pubkey const* c1_points[2] = {a_c1, b_c1};
if (secp256k1_ec_pubkey_combine(ctx, sum_c1, c1_points, 2) != 1)
{
return 0;
}
secp256k1_pubkey const* c2_points[2] = {a_c2, b_c2};
if (secp256k1_ec_pubkey_combine(ctx, sum_c2, c2_points, 2) != 1)
{
return 0;
}
return 1;
}
int
secp256k1_elgamal_subtract(
secp256k1_context const* ctx,
secp256k1_pubkey* diff_c1,
secp256k1_pubkey* diff_c2,
secp256k1_pubkey const* a_c1,
secp256k1_pubkey const* a_c2,
secp256k1_pubkey const* b_c1,
secp256k1_pubkey const* b_c2)
{
// To subtract, we add the negation: (A - B) is (A + (-B))
// Make a local, modifiable copy of B's points.
secp256k1_pubkey neg_b_c1 = *b_c1;
secp256k1_pubkey neg_b_c2 = *b_c2;
// Negate the copies
if (secp256k1_ec_pubkey_negate(ctx, &neg_b_c1) != 1 ||
secp256k1_ec_pubkey_negate(ctx, &neg_b_c2) != 1)
{
return 0; // Negation failed
}
// Now, add A and the negated copies of B
secp256k1_pubkey const* c1_points[2] = {a_c1, &neg_b_c1};
if (secp256k1_ec_pubkey_combine(ctx, diff_c1, c1_points, 2) != 1)
{
return 0;
}
secp256k1_pubkey const* c2_points[2] = {a_c2, &neg_b_c2};
if (secp256k1_ec_pubkey_combine(ctx, diff_c2, c2_points, 2) != 1)
{
return 0;
}
return 1; // Success
}
// Helper function to concatenate data for hashing
static void
build_hash_input(
unsigned char* output_buffer,
size_t buffer_size,
unsigned char const* account_id, // 20 bytes
unsigned char const* mpt_issuance_id // 24 bytes
)
{
char const* domain_separator = "EncZero";
size_t domain_len = strlen(domain_separator);
size_t offset = 0;
// Ensure buffer is large enough (should be checked by caller if necessary)
// Size = strlen("EncZero") + 20 + 24 = 7 + 20 + 24 = 51 bytes
memcpy(output_buffer + offset, domain_separator, domain_len);
offset += domain_len;
memcpy(output_buffer + offset, account_id, 20);
offset += 20;
memcpy(output_buffer + offset, mpt_issuance_id, 24);
// offset += 24; // Final size is offset + 24
}
// The canonical encrypted zero
int
generate_canonical_encrypted_zero(
secp256k1_context const* ctx,
secp256k1_pubkey* enc_zero_c1,
secp256k1_pubkey* enc_zero_c2,
secp256k1_pubkey const* pubkey,
unsigned char const* account_id, // 20 bytes
unsigned char const* mpt_issuance_id // 24 bytes
)
{
unsigned char deterministic_scalar[32];
unsigned char hash_input[51]; // Size calculated above
/* 1. Create the input buffer for hashing */
build_hash_input(
hash_input, sizeof(hash_input), account_id, mpt_issuance_id);
/* 2. Hash the buffer to create the deterministic scalar 'r' */
do
{
// Hash the concatenated bytes
SHA256(hash_input, sizeof(hash_input), deterministic_scalar);
/* Note: If the hash output could be invalid (0 or >= n),
* you might need to add a nonce/counter to hash_input
* and re-hash in a loop until a valid scalar is produced. */
} while (secp256k1_ec_seckey_verify(ctx, deterministic_scalar) != 1);
/* 3. Encrypt the amount 0 using the deterministic scalar */
return secp256k1_elgamal_encrypt(
ctx,
enc_zero_c1,
enc_zero_c2,
pubkey,
0, /* The amount is zero */
deterministic_scalar);
}
bool
makeEcPair(Slice const& buffer, secp256k1_pubkey& out1, secp256k1_pubkey& out2)
{
auto parsePubKey = [](Slice const& slice, secp256k1_pubkey& out) {
return secp256k1_ec_pubkey_parse(
secp256k1Context(),
&out,
reinterpret_cast<unsigned char const*>(slice.data()),
slice.length());
};
Slice s1{buffer.data(), ecGamalEncryptedLength};
Slice s2{buffer.data() + ecGamalEncryptedLength, ecGamalEncryptedLength};
int const ret1 = parsePubKey(s1, out1);
int const ret2 = parsePubKey(s2, out2);
return ret1 == 1 && ret2 == 1;
}
bool
serializeEcPair(
secp256k1_pubkey const& in1,
secp256k1_pubkey const& in2,
Buffer& buffer)
{
auto serializePubKey = [](secp256k1_pubkey const& pub, unsigned char* out) {
size_t outLen = ecGamalEncryptedLength; // 33 bytes
int const ret = secp256k1_ec_pubkey_serialize(
secp256k1Context(), out, &outLen, &pub, SECP256K1_EC_COMPRESSED);
return ret == 1 && outLen == ecGamalEncryptedLength;
};
unsigned char* ptr = buffer.data();
bool const res1 = serializePubKey(in1, ptr);
bool const res2 = serializePubKey(in2, ptr + ecGamalEncryptedLength);
return res1 && res2;
}
bool
isValidCiphertext(Slice const& buffer)
{
// Local/temporary variables to pass to makeEcPair.
// Their contents will be discarded when the function returns.
secp256k1_pubkey key1;
secp256k1_pubkey key2;
// Call makeEcPair and return its result.
return makeEcPair(buffer, key1, key2);
}
TER
homomorphicAdd(Slice const& a, Slice const& b, Buffer& out)
{
if (a.length() != ecGamalEncryptedTotalLength ||
b.length() != ecGamalEncryptedTotalLength)
return tecINTERNAL;
secp256k1_pubkey aC1;
secp256k1_pubkey aC2;
secp256k1_pubkey bC1;
secp256k1_pubkey bC2;
if (!makeEcPair(a, aC1, aC2) || !makeEcPair(b, bC1, bC2))
return tecINTERNAL;
secp256k1_pubkey sumC1;
secp256k1_pubkey sumC2;
if (secp256k1_elgamal_add(
secp256k1Context(), &sumC1, &sumC2, &aC1, &aC2, &bC1, &bC2) != 1)
return tecINTERNAL;
if (!serializeEcPair(sumC1, sumC2, out))
return tecINTERNAL;
return tesSUCCESS;
}
TER
homomorphicSubtract(Slice const& a, Slice const& b, Buffer& out)
{
if (a.length() != ecGamalEncryptedTotalLength ||
b.length() != ecGamalEncryptedTotalLength)
return tecINTERNAL;
secp256k1_pubkey aC1;
secp256k1_pubkey aC2;
secp256k1_pubkey bC1;
secp256k1_pubkey bC2;
if (!makeEcPair(a, aC1, aC2) || !makeEcPair(b, bC1, bC2))
return tecINTERNAL;
secp256k1_pubkey diffC1;
secp256k1_pubkey diffC2;
if (secp256k1_elgamal_subtract(
secp256k1Context(), &diffC1, &diffC2, &aC1, &aC2, &bC1, &bC2) != 1)
return tecINTERNAL;
if (!serializeEcPair(diffC1, diffC2, out))
return tecINTERNAL;
return tesSUCCESS;
}
TER
proveEquality(
Slice const& proof,
Slice const& encAmt, // encrypted amount
Slice const& pubkey,
uint64_t const amount,
uint256 const& txHash, // Transaction context data
std::uint32_t const spendVersion)
{
if (proof.length() != ecEqualityProofLength)
return tecINTERNAL;
secp256k1_pubkey c1;
secp256k1_pubkey c2;
if (!makeEcPair(encAmt, c1, c2))
return tecINTERNAL;
// todo: might need to change how its hashed
Serializer s;
s.addRaw(txHash.data(), txHash.bytes);
s.add32(spendVersion);
// auto const txContextId = s.getSHA512Half();
// todo: support equality
// if (secp256k1_equality_verify(
// secp256k1Context(),
// reinterpret_cast<unsigned char const*>(proof.data()),
// proof.length(), // Length of the proof byte array (98 bytes)
// &c1,
// &c2,
// reinterpret_cast<unsigned char const*>(pubkey.data()),
// amount,
// txContextId.data(), // Transaction context data
// txContextId.bytes // Length of context data
// ) != 1)
// return tecBAD_PROOF;
return tesSUCCESS;
}
Buffer
encryptAmount(uint64_t amt, Slice const& pubKeySlice)
{
Buffer buf(ecGamalEncryptedTotalLength);
// Allocate ciphertext placeholders
secp256k1_pubkey c1, c2;
// todo: might need to be updated using another RNG
// Prepare a random blinding factor
unsigned char blindingFactor[32];
if (RAND_bytes(blindingFactor, 32) != 1)
Throw<std::runtime_error>("Failed to generate random number");
secp256k1_pubkey pubKey;
std::memcpy(pubKey.data, pubKeySlice.data(), ecPubKeyLength);
// Encrypt the amount
if (!secp256k1_elgamal_encrypt(
secp256k1Context(), &c1, &c2, &pubKey, amt, blindingFactor))
Throw<std::runtime_error>("Failed to encrypt amount");
// Serialize the ciphertext pair into the buffer
if (!serializeEcPair(c1, c2, buf))
Throw<std::runtime_error>(
"Failed to serialize into 66 byte compressed format");
return buf;
}
Buffer
encryptCanonicalZeroAmount(
Slice const& pubKeySlice,
AccountID const& account,
MPTID const& mptId)
{
Buffer buf(ecGamalEncryptedTotalLength);
// Allocate ciphertext placeholders
secp256k1_pubkey c1, c2;
secp256k1_pubkey pubKey;
std::memcpy(pubKey.data, pubKeySlice.data(), ecPubKeyLength);
// Encrypt the amount
if (!generate_canonical_encrypted_zero(
secp256k1Context(),
&c1,
&c2,
&pubKey,
account.data(),
mptId.data()))
Throw<std::runtime_error>("Failed to encrypt amount");
// Serialize the ciphertext pair into the buffer
if (!serializeEcPair(c1, c2, buf))
Throw<std::runtime_error>(
"Failed to serialize into 66 byte compressed format");
return buf;
}
TER
verifyConfidentialSendProof(
Slice const& proof,
Slice const& encSenderBalance,
Slice const& encSenderAmt,
Slice const& encDestAmt,
Slice const& encIssuerAmt,
Slice const& senderPubKey,
Slice const& destPubKey,
Slice const& issuerPubKey,
std::uint32_t const version,
uint256 const& txHash)
{
// if (proof.length() != ecConfidentialSendProofLength)
// return tecINTERNAL;
secp256k1_pubkey balC1, balC2;
if (!makeEcPair(encSenderBalance, balC1, balC2))
return tecINTERNAL;
secp256k1_pubkey senderC1, senderC2;
if (!makeEcPair(encSenderAmt, senderC1, senderC2))
return tecINTERNAL;
secp256k1_pubkey destC1, destC2;
if (!makeEcPair(encDestAmt, destC1, destC2))
return tecINTERNAL;
secp256k1_pubkey issuerC1, issuerC2;
if (!makeEcPair(encIssuerAmt, issuerC1, issuerC2))
return tecINTERNAL;
Serializer s;
s.addRaw(txHash.data(), txHash.bytes);
s.add32(version);
// auto const txContextId = s.getSHA512Half();
// todo: equality and range proof verification
// if (secp256k1_equal_range_verify(
// secp256k1Context(),
// reinterpret_cast<unsigned char const*>(proof.data()),
// proof.length(),
// txContextId.data(),
// &balC1,
// &balC2,
// &senderC1,
// &senderC2,
// reinterpret_cast<unsigned char const*>(senderPubKey.data()),
// &destC1,
// &destC2,
// reinterpret_cast<unsigned char const*>(destPubKey.data()),
// &issuerC1,
// &issuerC2,
// reinterpret_cast<unsigned char const*>(issuerPubKey.data()),
// txContextId.data(),
// txContextId.bytes) != 1)
// return tecBAD_PROOF;
return tesSUCCESS;
}
} // namespace ripple

View File

@@ -101,22 +101,6 @@ Permission::getInstance()
return instance;
}
std::optional<std::string>
Permission::getPermissionName(std::uint32_t const value) const
{
auto const permissionValue = static_cast<GranularPermissionType>(value);
if (auto const granular = getGranularName(permissionValue))
return *granular;
// not a granular permission, check if it maps to a transaction type
auto const txType = permissionToTxType(value);
if (auto const* item = TxFormats::getInstance().findByType(txType);
item != nullptr)
return item->getName();
return std::nullopt;
}
std::optional<std::uint32_t>
Permission::getGranularValue(std::string const& name) const
{
@@ -147,19 +131,6 @@ Permission::getGranularTxType(GranularPermissionType const& gpType) const
return std::nullopt;
}
std::optional<std::reference_wrapper<uint256 const>> const
Permission::getTxFeature(TxType txType) const
{
auto const txFeaturesIt = txFeatureMap_.find(txType);
XRPL_ASSERT(
txFeaturesIt != txFeatureMap_.end(),
"ripple::Permissions::getTxFeature : tx exists in txFeatureMap_");
if (txFeaturesIt->second == uint256{})
return std::nullopt;
return txFeaturesIt->second;
}
bool
Permission::isDelegatable(
std::uint32_t const& permissionValue,
@@ -174,22 +145,25 @@ Permission::isDelegatable(
auto const txType = permissionToTxType(permissionValue);
auto const it = delegatableTx_.find(txType);
if (it == delegatableTx_.end())
return false;
if (rules.enabled(fixDelegateV1_1))
{
if (it == delegatableTx_.end())
return false;
auto const txFeaturesIt = txFeatureMap_.find(txType);
XRPL_ASSERT(
txFeaturesIt != txFeatureMap_.end(),
"ripple::Permissions::isDelegatable : tx exists in txFeatureMap_");
auto const txFeaturesIt = txFeatureMap_.find(txType);
XRPL_ASSERT(
txFeaturesIt != txFeatureMap_.end(),
"ripple::Permissions::isDelegatable : tx exists in txFeatureMap_");
// Delegation is only allowed if the required amendment for the transaction
// is enabled. For transactions that do not require an amendment, delegation
// is always allowed.
if (txFeaturesIt->second != uint256{} &&
!rules.enabled(txFeaturesIt->second))
return false;
// fixDelegateV1_1: Delegation is only allowed if the required amendment
// for the transaction is enabled. For transactions that do not require
// an amendment, delegation is always allowed.
if (txFeaturesIt->second != uint256{} &&
!rules.enabled(txFeaturesIt->second))
return false;
}
if (it->second == Delegation::notDelegatable)
if (it != delegatableTx_.end() && it->second == Delegation::notDelegatable)
return false;
return true;

View File

@@ -131,6 +131,17 @@ Rules::enabled(uint256 const& feature) const
{
XRPL_ASSERT(impl_, "ripple::Rules::enabled : initialized");
// The functionality of the "NonFungibleTokensV1_1" amendment is
// precisely the functionality of the following three amendments
// so if their status is ever queried individually, we inject an
// extra check here to simplify the checking elsewhere.
if (feature == featureNonFungibleTokensV1 ||
feature == fixNFTokenNegOffer || feature == fixNFTokenDirV1)
{
if (impl_->enabled(featureNonFungibleTokensV1_1))
return true;
}
return impl_->enabled(feature);
}

View File

@@ -17,7 +17,6 @@
*/
//==============================================================================
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/protocol/SField.h>
#include <map>
@@ -28,8 +27,7 @@ namespace ripple {
// Storage for static const members.
SField::IsSigning const SField::notSigning;
int SField::num = 0;
std::unordered_map<int, SField const*> SField::knownCodeToField;
std::unordered_map<std::string, SField const*> SField::knownNameToField;
std::map<int, SField const*> SField::knownCodeToField;
// Give only this translation unit permission to construct SFields
struct SField::private_access_tag_t
@@ -47,7 +45,7 @@ TypedField<T>::TypedField(private_access_tag_t pat, Args&&... args)
}
// Construct all compile-time SFields, and register them in the knownCodeToField
// and knownNameToField databases:
// database:
// Use macros for most SField construction to enforce naming conventions.
#pragma push_macro("UNTYPED_SFIELD")
@@ -71,8 +69,8 @@ TypedField<T>::TypedField(private_access_tag_t pat, Args&&... args)
##__VA_ARGS__);
// SFields which, for historical reasons, do not follow naming conventions.
SField const sfInvalid(access, -1, "");
SField const sfGeneric(access, 0, "Generic");
SField const sfInvalid(access, -1);
SField const sfGeneric(access, 0);
// The following two fields aren't used anywhere, but they break tests/have
// downstream effects.
SField const sfHash(access, STI_UINT256, 257, "hash");
@@ -101,34 +99,19 @@ SField::SField(
, signingField(signing)
, jsonName(fieldName.c_str())
{
XRPL_ASSERT(
!knownCodeToField.contains(fieldCode),
"ripple::SField::SField(tid,fv,fn,meta,signing) : fieldCode is unique");
XRPL_ASSERT(
!knownNameToField.contains(fieldName),
"ripple::SField::SField(tid,fv,fn,meta,signing) : fieldName is unique");
knownCodeToField[fieldCode] = this;
knownNameToField[fieldName] = this;
}
SField::SField(private_access_tag_t, int fc, char const* fn)
SField::SField(private_access_tag_t, int fc)
: fieldCode(fc)
, fieldType(STI_UNKNOWN)
, fieldValue(0)
, fieldName(fn)
, fieldMeta(sMD_Never)
, fieldNum(++num)
, signingField(IsSigning::yes)
, jsonName(fieldName.c_str())
{
XRPL_ASSERT(
!knownCodeToField.contains(fieldCode),
"ripple::SField::SField(fc,fn) : fieldCode is unique");
XRPL_ASSERT(
!knownNameToField.contains(fieldName),
"ripple::SField::SField(fc,fn) : fieldName is unique");
knownCodeToField[fieldCode] = this;
knownNameToField[fieldName] = this;
}
SField const&
@@ -162,11 +145,11 @@ SField::compare(SField const& f1, SField const& f2)
SField const&
SField::getField(std::string const& fieldName)
{
auto it = knownNameToField.find(fieldName);
if (it != knownNameToField.end())
for (auto const& [_, f] : knownCodeToField)
{
return *(it->second);
(void)_;
if (f->fieldName == fieldName)
return *f;
}
return sfInvalid;
}

View File

@@ -68,6 +68,29 @@
namespace ripple {
namespace {
// Use a static inside a function to help prevent order-of-initialzation issues
LocalValue<bool>&
getStaticSTAmountCanonicalizeSwitchover()
{
static LocalValue<bool> r{true};
return r;
}
} // namespace
bool
getSTAmountCanonicalizeSwitchover()
{
return *getStaticSTAmountCanonicalizeSwitchover();
}
void
setSTAmountCanonicalizeSwitchover(bool v)
{
*getStaticSTAmountCanonicalizeSwitchover() = v;
}
static std::uint64_t const tenTo14 = 100000000000000ull;
static std::uint64_t const tenTo14m1 = tenTo14 - 1;
static std::uint64_t const tenTo17 = tenTo14 * 1000;
@@ -861,14 +884,18 @@ STAmount::canonicalize()
return;
}
// log(cMaxNativeN, 10) == 17
if (native() && mOffset > 17)
Throw<std::runtime_error>("Native currency amount out of range");
// log(maxMPTokenAmount, 10) ~ 18.96
if (mAsset.holds<MPTIssue>() && mOffset > 18)
Throw<std::runtime_error>("MPT amount out of range");
if (getSTAmountCanonicalizeSwitchover())
{
// log(cMaxNativeN, 10) == 17
if (native() && mOffset > 17)
Throw<std::runtime_error>(
"Native currency amount out of range");
// log(maxMPTokenAmount, 10) ~ 18.96
if (mAsset.holds<MPTIssue>() && mOffset > 18)
Throw<std::runtime_error>("MPT amount out of range");
}
if (getSTNumberSwitchover())
if (getSTNumberSwitchover() && getSTAmountCanonicalizeSwitchover())
{
Number num(
mIsNegative ? -mValue : mValue, mOffset, Number::unchecked{});
@@ -892,14 +919,16 @@ STAmount::canonicalize()
while (mOffset > 0)
{
// N.B. do not move the overflow check to after the
// multiplication
if (native() && mValue > cMaxNativeN)
Throw<std::runtime_error>(
"Native currency amount out of range");
else if (!native() && mValue > maxMPTokenAmount)
Throw<std::runtime_error>("MPT amount out of range");
if (getSTAmountCanonicalizeSwitchover())
{
// N.B. do not move the overflow check to after the
// multiplication
if (native() && mValue > cMaxNativeN)
Throw<std::runtime_error>(
"Native currency amount out of range");
else if (!native() && mValue > maxMPTokenAmount)
Throw<std::runtime_error>("MPT amount out of range");
}
mValue *= 10;
--mOffset;
}

View File

@@ -112,9 +112,7 @@ void
STBase::add(Serializer& s) const
{
// Should never be called
// LCOV_EXCL_START
UNREACHABLE("ripple::STBase::add : not implemented");
// LCOV_EXCL_STOP
}
bool

View File

@@ -62,10 +62,8 @@ STUInt8::getText() const
if (transResultInfo(TER::fromInt(value_), token, human))
return human;
// LCOV_EXCL_START
JLOG(debugLog().error())
<< "Unknown result code in metadata: " << value_;
// LCOV_EXCL_STOP
}
return std::to_string(value_);
@@ -82,10 +80,8 @@ STUInt8::getJson(JsonOptions) const
if (transResultInfo(TER::fromInt(value_), token, human))
return token;
// LCOV_EXCL_START
JLOG(debugLog().error())
<< "Unknown result code in metadata: " << value_;
// LCOV_EXCL_STOP
}
return value_;
@@ -175,13 +171,6 @@ template <>
std::string
STUInt32::getText() const
{
if (getFName() == sfPermissionValue)
{
auto const permissionName =
Permission::getInstance().getPermissionName(value_);
if (permissionName)
return *permissionName;
}
return std::to_string(value_);
}
@@ -191,10 +180,23 @@ STUInt32::getJson(JsonOptions) const
{
if (getFName() == sfPermissionValue)
{
auto const permissionName =
Permission::getInstance().getPermissionName(value_);
if (permissionName)
return *permissionName;
auto const permissionValue =
static_cast<GranularPermissionType>(value_);
auto const granular =
Permission::getInstance().getGranularName(permissionValue);
if (granular)
{
return *granular;
}
else
{
auto const txType =
Permission::getInstance().permissionToTxType(value_);
auto item = TxFormats::getInstance().findByType(txType);
if (item != nullptr)
return item->getName();
}
}
return value_;
@@ -249,33 +251,4 @@ STUInt64::getJson(JsonOptions) const
return convertToString(value_, 16); // Convert to base 16
}
//------------------------------------------------------------------------------
template <>
STInteger<std::int32_t>::STInteger(SerialIter& sit, SField const& name)
: STInteger(name, sit.get32())
{
}
template <>
SerializedTypeID
STInt32::getSType() const
{
return STI_INT32;
}
template <>
std::string
STInt32::getText() const
{
return std::to_string(value_);
}
template <>
Json::Value
STInt32::getJson(JsonOptions) const
{
return value_;
}
} // namespace ripple

View File

@@ -647,12 +647,6 @@ STObject::getFieldH256(SField const& field) const
return getFieldByValue<STUInt256>(field);
}
std::int32_t
STObject::getFieldI32(SField const& field) const
{
return getFieldByValue<STInt32>(field);
}
AccountID
STObject::getAccountID(SField const& field) const
{
@@ -688,16 +682,6 @@ STObject::getFieldV256(SField const& field) const
return getFieldByConstRef<STVector256>(field, empty);
}
STObject
STObject::getFieldObject(SField const& field) const
{
STObject const empty{field};
auto ret = getFieldByConstRef<STObject>(field, empty);
if (ret != empty)
ret.applyTemplateFromSField(field);
return ret;
}
STArray const&
STObject::getFieldArray(SField const& field) const
{
@@ -777,12 +761,6 @@ STObject::setFieldH256(SField const& field, uint256 const& v)
setFieldUsingSetValue<STUInt256>(field, v);
}
void
STObject::setFieldI32(SField const& field, std::int32_t v)
{
setFieldUsingSetValue<STInt32>(field, v);
}
void
STObject::setFieldV256(SField const& field, STVector256 const& v)
{
@@ -843,12 +821,6 @@ STObject::setFieldArray(SField const& field, STArray const& v)
setFieldUsingAssignment(field, v);
}
void
STObject::setFieldObject(SField const& field, STObject const& v)
{
setFieldUsingAssignment(field, v);
}
Json::Value
STObject::getJson(JsonOptions options) const
{

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