Compare commits

..

1 Commits

Author SHA1 Message Date
Michael Legleux
8ef1811f63 feat: Build Linux packages in GitHub 2026-03-24 15:42:27 -07:00
144 changed files with 1722 additions and 827 deletions

View File

@@ -90,7 +90,6 @@ test.core > xrpl.server
test.csf > xrpl.basics
test.csf > xrpld.consensus
test.csf > xrpl.json
test.csf > xrpl.ledger
test.csf > xrpl.protocol
test.json > test.jtx
test.json > xrpl.json
@@ -109,6 +108,7 @@ test.jtx > xrpl.tx
test.ledger > test.jtx
test.ledger > test.toplevel
test.ledger > xrpl.basics
test.ledger > xrpld.app
test.ledger > xrpld.core
test.ledger > xrpl.ledger
test.ledger > xrpl.protocol
@@ -125,7 +125,6 @@ test.overlay > xrpl.basics
test.overlay > xrpld.app
test.overlay > xrpld.overlay
test.overlay > xrpld.peerfinder
test.overlay > xrpl.ledger
test.overlay > xrpl.nodestore
test.overlay > xrpl.protocol
test.overlay > xrpl.shamap
@@ -235,7 +234,6 @@ xrpld.app > xrpl.shamap
xrpld.app > xrpl.tx
xrpld.consensus > xrpl.basics
xrpld.consensus > xrpl.json
xrpld.consensus > xrpl.ledger
xrpld.consensus > xrpl.protocol
xrpld.core > xrpl.basics
xrpld.core > xrpl.core

View File

@@ -99,14 +99,15 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
continue
# RHEL:
# - 9 using GCC 12: Debug on linux/amd64.
# - 9 using GCC 12: Debug and Release on linux/amd64
# (Release is required for RPM packaging).
# - 10 using Clang: Release on linux/amd64.
if os["distro_name"] == "rhel":
skip = True
if os["distro_version"] == "9":
if (
f"{os['compiler_name']}-{os['compiler_version']}" == "gcc-12"
and build_type == "Debug"
and build_type in ["Debug", "Release"]
and architecture["platform"] == "linux/amd64"
):
skip = False
@@ -121,7 +122,8 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
continue
# Ubuntu:
# - Jammy using GCC 12: Debug on linux/arm64.
# - Jammy using GCC 12: Debug on linux/arm64, Release on
# linux/amd64 (Release is required for DEB packaging).
# - Noble using GCC 14: Release on linux/amd64.
# - Noble using Clang 18: Debug on linux/amd64.
# - Noble using Clang 19: Release on linux/arm64.
@@ -134,6 +136,12 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
and architecture["platform"] == "linux/arm64"
):
skip = False
if (
f"{os['compiler_name']}-{os['compiler_version']}" == "gcc-12"
and build_type == "Release"
and architecture["platform"] == "linux/amd64"
):
skip = False
elif os["distro_version"] == "noble":
if (
f"{os['compiler_name']}-{os['compiler_version']}" == "gcc-14"

View File

@@ -1,25 +0,0 @@
name: Label PRs with merge conflicts
on:
# So that PRs touching the same files as the push are updated.
push:
# So that the `dirtyLabel` is removed if conflicts are resolved.
# We recommend `pull_request_target` so that github secrets are available.
# In `pull_request` we wouldn't be able to change labels of fork PRs.
pull_request_target:
types: [synchronize]
permissions:
pull-requests: write
jobs:
main:
runs-on: ubuntu-latest
steps:
- name: Check if PRs are dirty
uses: eps1lon/actions-label-merge-conflict@1df065ebe6e3310545d4f4c4e862e43bdca146f0 # v3.0.3
with:
dirtyLabel: "PR: has conflicts"
repoToken: "${{ secrets.GITHUB_TOKEN }}"
commentOnDirty: "This PR has conflicts, please resolve them in order for the PR to be reviewed."
commentOnClean: "All conflicts have been resolved. Assigned reviewers can now start or resume their review."

66
.github/workflows/manual-package.yml vendored Normal file
View File

@@ -0,0 +1,66 @@
name: Manual Package Build
on:
workflow_dispatch:
inputs:
pkg_type:
description: "Package type"
required: true
type: choice
options:
- deb
- rpm
- both
artifact_run_id:
description: "Run ID to download binary artifact from (leave empty for latest on this branch)"
required: false
type: string
version:
description: "Version override (leave empty to auto-detect)"
required: false
type: string
pkg_release:
description: "Package release number (default: 1)"
required: false
type: string
default: "1"
defaults:
run:
shell: bash
jobs:
generate-version:
runs-on: ubuntu-latest
outputs:
version: ${{ inputs.version || steps.version.outputs.version }}
steps:
- name: Checkout repository
if: ${{ !inputs.version }}
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Generate version
if: ${{ !inputs.version }}
id: version
uses: ./.github/actions/generate-version
package-deb:
if: ${{ inputs.pkg_type == 'deb' || inputs.pkg_type == 'both' }}
needs: generate-version
uses: ./.github/workflows/reusable-package.yml
with:
pkg_type: deb
artifact_name: xrpld-ubuntu-jammy-gcc-12-amd64-release
version: ${{ needs.generate-version.outputs.version }}
pkg_release: ${{ inputs.pkg_release }}
container_image: ghcr.io/xrplf/ci/ubuntu-jammy:gcc-12
package-rpm:
if: ${{ inputs.pkg_type == 'rpm' || inputs.pkg_type == 'both' }}
needs: generate-version
uses: ./.github/workflows/reusable-package.yml
with:
pkg_type: rpm
artifact_name: xrpld-rhel-9-gcc-12-amd64-release
version: ${{ needs.generate-version.outputs.version }}
pkg_release: ${{ inputs.pkg_release }}
container_image: ghcr.io/xrplf/ci/rhel-9:gcc-12

View File

@@ -67,6 +67,7 @@ jobs:
.github/workflows/reusable-build-test.yml
.github/workflows/reusable-clang-tidy.yml
.github/workflows/reusable-clang-tidy-files.yml
.github/workflows/reusable-package.yml
.github/workflows/reusable-strategy-matrix.yml
.github/workflows/reusable-test.yml
.github/workflows/reusable-upload-recipe.yml
@@ -81,6 +82,8 @@ jobs:
CMakeLists.txt
conanfile.py
conan.lock
package/**
- name: Check whether to run
# This step determines whether the rest of the workflow should
# run. The rest of the workflow will run if this job runs AND at
@@ -137,6 +140,39 @@ jobs:
secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
generate-version:
needs: should-run
if: ${{ needs.should-run.outputs.go == 'true' }}
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Generate version
id: version
uses: ./.github/actions/generate-version
package-deb:
needs: [should-run, build-test, generate-version]
if: ${{ needs.should-run.outputs.go == 'true' }}
uses: ./.github/workflows/reusable-package.yml
with:
pkg_type: deb
artifact_name: xrpld-ubuntu-jammy-gcc-12-amd64-release
version: ${{ needs.generate-version.outputs.version }}
container_image: ghcr.io/xrplf/ci/ubuntu-jammy:gcc-12
package-rpm:
needs: [should-run, build-test, generate-version]
if: ${{ needs.should-run.outputs.go == 'true' }}
uses: ./.github/workflows/reusable-package.yml
with:
pkg_type: rpm
artifact_name: xrpld-rhel-9-gcc-12-amd64-release
version: ${{ needs.generate-version.outputs.version }}
container_image: ghcr.io/xrplf/ci/rhel-9:gcc-12
upload-recipe:
needs:
- should-run

View File

@@ -1,5 +1,5 @@
# This workflow uploads the libxrpl recipe to the Conan remote when a versioned
# tag is pushed.
# This workflow uploads the libxrpl recipe to the Conan remote and builds
# release packages when a versioned tag is pushed.
name: Tag
on:
@@ -22,3 +22,49 @@ jobs:
secrets:
remote_username: ${{ secrets.CONAN_REMOTE_USERNAME }}
remote_password: ${{ secrets.CONAN_REMOTE_PASSWORD }}
build-test:
if: ${{ github.repository == 'XRPLF/rippled' }}
uses: ./.github/workflows/reusable-build-test.yml
strategy:
fail-fast: true
matrix:
os: [linux]
with:
ccache_enabled: false
os: ${{ matrix.os }}
strategy_matrix: minimal
secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
generate-version:
if: ${{ github.repository == 'XRPLF/rippled' }}
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Generate version
id: version
uses: ./.github/actions/generate-version
package-deb:
needs: [build-test, generate-version]
if: ${{ github.repository == 'XRPLF/rippled' }}
uses: ./.github/workflows/reusable-package.yml
with:
pkg_type: deb
artifact_name: xrpld-ubuntu-jammy-gcc-12-amd64-release
version: ${{ needs.generate-version.outputs.version }}
container_image: ghcr.io/xrplf/ci/ubuntu-jammy:gcc-12
package-rpm:
needs: [build-test, generate-version]
if: ${{ github.repository == 'XRPLF/rippled' }}
uses: ./.github/workflows/reusable-package.yml
with:
pkg_type: rpm
artifact_name: xrpld-rhel-9-gcc-12-amd64-release
version: ${{ needs.generate-version.outputs.version }}
container_image: ghcr.io/xrplf/ci/rhel-9:gcc-12

View File

@@ -38,6 +38,8 @@ on:
- "CMakeLists.txt"
- "conanfile.py"
- "conan.lock"
- "package/**"
- ".github/workflows/reusable-package.yml"
# Run at 06:32 UTC on every day of the week from Monday through Friday. This
# will force all dependencies to be rebuilt, which is useful to verify that
@@ -77,7 +79,7 @@ jobs:
strategy:
fail-fast: ${{ github.event_name == 'merge_group' }}
matrix:
os: [linux, macos, windows]
os: [linux]
with:
# Enable ccache only for events targeting the XRPLF repository, since
# other accounts will not have access to our remote cache storage.
@@ -98,3 +100,32 @@ jobs:
secrets:
remote_username: ${{ secrets.CONAN_REMOTE_USERNAME }}
remote_password: ${{ secrets.CONAN_REMOTE_PASSWORD }}
generate-version:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Generate version
id: version
uses: ./.github/actions/generate-version
package-deb:
needs: [build-test, generate-version]
uses: ./.github/workflows/reusable-package.yml
with:
pkg_type: deb
artifact_name: xrpld-ubuntu-jammy-gcc-12-amd64-release
version: ${{ needs.generate-version.outputs.version }}
container_image: ghcr.io/xrplf/ci/ubuntu-jammy:gcc-12
package-rpm:
needs: [build-test, generate-version]
uses: ./.github/workflows/reusable-package.yml
with:
pkg_type: rpm
artifact_name: xrpld-rhel-9-gcc-12-amd64-release
version: ${{ needs.generate-version.outputs.version }}
container_image: ghcr.io/xrplf/ci/rhel-9:gcc-12

View File

@@ -51,5 +51,5 @@ jobs:
if: ${{ always() && !cancelled() && (!inputs.check_only_changed || needs.determine-files.outputs.any_cpp_changed == 'true' || needs.determine-files.outputs.clang_tidy_config_changed == 'true') }}
uses: ./.github/workflows/reusable-clang-tidy-files.yml
with:
files: ${{ (needs.determine-files.outputs.clang_tidy_config_changed != 'true' && inputs.check_only_changed) && needs.determine-files.outputs.all_changed_files || '' }}
files: ${{ needs.determine-files.outputs.clang_tidy_config_changed == 'true' && '' || (inputs.check_only_changed && needs.determine-files.outputs.all_changed_files || '') }}
create_issue_on_failure: ${{ inputs.create_issue_on_failure }}

76
.github/workflows/reusable-package.yml vendored Normal file
View File

@@ -0,0 +1,76 @@
# Build a Linux package (DEB or RPM) from a pre-built binary artifact.
name: Package
on:
workflow_call:
inputs:
pkg_type:
description: "Package type to build: deb or rpm."
required: true
type: string
artifact_name:
description: "Name of the pre-built binary artifact to download."
required: true
type: string
version:
description: "Version string used for naming the output artifact."
required: true
type: string
pkg_release:
description: "Package release number. Increment when repackaging the same executable."
required: false
type: string
default: "1"
container_image:
description: "Container image to use for packaging."
required: true
type: string
defaults:
run:
shell: bash
env:
BUILD_DIR: build
jobs:
package:
name: ${{ inputs.pkg_type }} (${{ inputs.version }})
runs-on: ["self-hosted", "Linux", "X64", "heavy"]
container: ${{ inputs.container_image }}
timeout-minutes: 30
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Download pre-built binary
uses: actions/download-artifact@v4
with:
name: ${{ inputs.artifact_name }}
path: ${{ env.BUILD_DIR }}
- name: Make binary executable
run: chmod +x ${{ env.BUILD_DIR }}/xrpld
- name: Generate RPM spec from template
if: ${{ inputs.pkg_type == 'rpm' }}
run: |
mkdir -p ${{ env.BUILD_DIR }}/package/rpm
sed -e "s/@xrpld_version@/${{ inputs.version }}/" \
-e "s/@pkg_release@/${{ inputs.pkg_release }}/" \
package/rpm/xrpld.spec.in > ${{ env.BUILD_DIR }}/package/rpm/xrpld.spec
- name: Build package
run: |
./package/build_pkg.sh ${{ inputs.pkg_type }} . ${{ env.BUILD_DIR }} "${{ inputs.version }}" "${{ inputs.pkg_release }}"
- name: Upload package artifact
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: xrpld-${{ inputs.pkg_type }}-${{ inputs.version }}
path: |
${{ env.BUILD_DIR }}/debbuild/*.deb
${{ env.BUILD_DIR }}/debbuild/*.ddeb
${{ env.BUILD_DIR }}/rpmbuild/RPMS/**/*.rpm
if-no-files-found: error

2
.gitignore vendored
View File

@@ -71,8 +71,6 @@ DerivedData
/.zed/
# AI tools.
/.agent
/.agents
/.augment
/.claude
/CLAUDE.md

View File

@@ -125,9 +125,9 @@ default profile.
### Patched recipes
Occasionally, we need patched recipes or recipes not present in Conan Center.
We maintain a fork of the Conan Center Index
[here](https://github.com/XRPLF/conan-center-index/) containing the modified and newly added recipes.
The recipes in Conan Center occasionally need to be patched for compatibility
with the latest version of `xrpld`. We maintain a fork of the Conan Center
[here](https://github.com/XRPLF/conan-center-index/) containing the patches.
To ensure our patched recipes are used, you must add our Conan remote at a
higher index than the default Conan Center remote, so it is consulted first. You
@@ -137,11 +137,19 @@ can do this by running:
conan remote add --index 0 xrplf https://conan.ripplex.io
```
Alternatively, you can pull our recipes from the repository and export them locally:
Alternatively, you can pull the patched recipes into the repository and use them
locally:
```bash
# Extract the version number from the lockfile.
function extract_version {
version=$(cat conan.lock | sed -nE "s@.+${1}/(.+)#.+@\1@p" | head -n1)
echo ${version}
}
# Define which recipes to export.
recipes=('abseil' 'ed25519' 'grpc' 'm4' 'mpt-crypto' 'nudb' 'openssl' 'secp256k1' 'snappy' 'soci' 'wasm-xrplf' 'wasmi')
recipes=('ed25519' 'grpc' 'nudb' 'openssl' 'secp256k1' 'snappy' 'soci')
folders=('all' 'all' 'all' '3.x.x' 'all' 'all' 'all')
# Selectively check out the recipes from our CCI fork.
cd external
@@ -150,19 +158,29 @@ cd conan-center-index
git init
git remote add origin git@github.com:XRPLF/conan-center-index.git
git sparse-checkout init
for recipe in "${recipes[@]}"; do
echo "Checking out recipe '${recipe}'..."
git sparse-checkout add recipes/${recipe}
for ((index = 1; index <= ${#recipes[@]}; index++)); do
recipe=${recipes[index]}
folder=${folders[index]}
echo "Checking out recipe '${recipe}' from folder '${folder}'..."
git sparse-checkout add recipes/${recipe}/${folder}
done
git fetch origin master
git checkout master
cd ../..
./export_all.sh
cd ../../
# Export the recipes into the local cache.
for ((index = 1; index <= ${#recipes[@]}; index++)); do
recipe=${recipes[index]}
folder=${folders[index]}
version=$(extract_version ${recipe})
echo "Exporting '${recipe}/${version}' from '${recipe}/${folder}'..."
conan export --version $(extract_version ${recipe}) \
external/conan-center-index/recipes/${recipe}/${folder}
done
```
In the case we switch to a newer version of a dependency that still requires a
patch or add a new dependency, it will be necessary for you to pull in the changes and re-export the
patch, it will be necessary for you to pull in the changes and re-export the
updated dependencies with the newer version. However, if we switch to a newer
version that no longer requires a patch, no action is required on your part, as
the new recipe will be automatically pulled from the official Conan Center.
@@ -171,8 +189,6 @@ the new recipe will be automatically pulled from the official Conan Center.
> You might need to add `--lockfile=""` to your `conan install` command
> to avoid automatic use of the existing `conan.lock` file when you run
> `conan export` manually on your machine
>
> This is not recommended though, as you might end up using different revisions of recipes.
### Conan profile tweaks
@@ -188,14 +204,39 @@ Possible values are ['5.0', '5.1', '6.0', '6.1', '7.0', '7.3', '8.0', '8.1',
Read "http://docs.conan.io/2/knowledge/faq.html#error-invalid-setting"
```
you need to add your compiler to the list of compiler versions in
`$(conan config home)/settings_user.yml`, by adding the required version number(s)
you need to amend the list of compiler versions in
`$(conan config home)/settings.yml`, by appending the required version number(s)
to the `version` array specific for your compiler. For example:
```yaml
compiler:
apple-clang:
version: ["17.0"]
apple-clang:
version:
[
"5.0",
"5.1",
"6.0",
"6.1",
"7.0",
"7.3",
"8.0",
"8.1",
"9.0",
"9.1",
"10.0",
"11.0",
"12.0",
"13",
"13.0",
"13.1",
"14",
"14.0",
"15",
"15.0",
"16",
"16.0",
"17",
"17.0",
]
```
#### Multiple compilers

View File

@@ -133,6 +133,7 @@ endif()
include(XrplCore)
include(XrplInstall)
include(XrplPackaging)
include(XrplValidatorKeys)
if(tests)

View File

@@ -259,10 +259,6 @@ There is a Continuous Integration job that runs clang-tidy on pull requests. The
This ensures that configuration changes don't introduce new warnings across the codebase.
### Installing clang-tidy
See the [environment setup guide](./docs/build/environment.md#clang-tidy) for platform-specific installation instructions.
### Running clang-tidy locally
Before running clang-tidy, you must build the project to generate required files (particularly protobuf headers). Refer to [`BUILD.md`](./BUILD.md) for build instructions.
@@ -270,15 +266,10 @@ Before running clang-tidy, you must build the project to generate required files
Then run clang-tidy on your local changes:
```
run-clang-tidy -p build src include tests
run-clang-tidy -p build src tests
```
This will check all source files in the `src`, `include` and `tests` directories using the compile commands from your `build` directory.
If you wish to automatically fix whatever clang-tidy finds _and_ is capable of fixing, add `-fix` to the above command:
```
run-clang-tidy -p build -fix src include tests
```
This will check all source files in the `src` and `tests` directories using the compile commands from your `build` directory.
## Contracts and instrumentation

View File

@@ -1,7 +1,7 @@
ISC License
Copyright (c) 2011, Arthur Britto, David Schwartz, Jed McCaleb, Vinnie Falco, Bob Way, Eric Lombrozo, Nikolaos D. Bougalis, Howard Hinnant.
Copyright (c) 2012-present, the XRP Ledger developers.
Copyright (c) 2012-2025, the XRP Ledger developers.
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above

View File

@@ -12,14 +12,14 @@ if(is_root_project AND TARGET xrpld)
install(
FILES "${CMAKE_CURRENT_SOURCE_DIR}/cfg/xrpld-example.cfg"
DESTINATION "${CMAKE_INSTALL_SYSCONFDIR}/xrpld"
DESTINATION "${CMAKE_INSTALL_SYSCONFDIR}"
RENAME xrpld.cfg
COMPONENT runtime
)
install(
FILES "${CMAKE_CURRENT_SOURCE_DIR}/cfg/validators-example.txt"
DESTINATION "${CMAKE_INSTALL_SYSCONFDIR}/xrpld"
DESTINATION "${CMAKE_INSTALL_SYSCONFDIR}"
RENAME validators.txt
COMPONENT runtime
)

147
cmake/XrplPackaging.cmake Normal file
View File

@@ -0,0 +1,147 @@
#[===================================================================[
Linux packaging support: RPM and Debian targets + install tests
#]===================================================================]
if(NOT CMAKE_INSTALL_PREFIX STREQUAL "/opt/xrpld")
message(
STATUS
"Packaging targets require -DCMAKE_INSTALL_PREFIX=/opt/xrpld "
"(current: '${CMAKE_INSTALL_PREFIX}'); skipping."
)
return()
endif()
# Generate the RPM spec from template (substitutes @xrpld_version@, @pkg_release@).
if(NOT DEFINED pkg_release)
set(pkg_release 1)
endif()
configure_file(
${CMAKE_SOURCE_DIR}/package/rpm/xrpld.spec.in
${CMAKE_BINARY_DIR}/package/rpm/xrpld.spec
@ONLY
)
find_program(RPMBUILD_EXECUTABLE rpmbuild)
if(RPMBUILD_EXECUTABLE)
add_custom_target(
package-rpm
COMMAND
${CMAKE_SOURCE_DIR}/package/build_pkg.sh rpm ${CMAKE_SOURCE_DIR}
${CMAKE_BINARY_DIR}
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
COMMENT "Building RPM package"
VERBATIM
)
else()
message(STATUS "rpmbuild not found; 'package-rpm' target not available")
endif()
find_program(DPKG_BUILDPACKAGE_EXECUTABLE dpkg-buildpackage)
if(DPKG_BUILDPACKAGE_EXECUTABLE)
add_custom_target(
package-deb
COMMAND
${CMAKE_SOURCE_DIR}/package/build_pkg.sh deb ${CMAKE_SOURCE_DIR}
${CMAKE_BINARY_DIR} ${xrpld_version}
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
COMMENT "Building Debian package"
VERBATIM
)
else()
message(
STATUS
"dpkg-buildpackage not found; 'package-deb' target not available"
)
endif()
#[===================================================================[
CTest fixtures for package install verification (requires docker)
#]===================================================================]
find_program(DOCKER_EXECUTABLE docker)
if(NOT DOCKER_EXECUTABLE)
message(STATUS "docker not found; package install tests not available")
return()
endif()
set(DEB_TEST_IMAGE "geerlingguy/docker-ubuntu2204-ansible:latest")
set(RPM_TEST_IMAGE "geerlingguy/docker-rockylinux9-ansible:latest")
foreach(PKG deb rpm)
if(PKG STREQUAL "deb")
set(IMAGE ${DEB_TEST_IMAGE})
else()
set(IMAGE ${RPM_TEST_IMAGE})
endif()
# Fixture: start container
add_test(
NAME ${PKG}_container_start
COMMAND
sh -c
"docker rm -f xrpld_${PKG}_install_test 2>/dev/null || true && \
docker run --rm -d \
--name xrpld_${PKG}_install_test \
--memory=45g --memory-swap=45g \
--privileged \
--cgroupns host \
--volume '${CMAKE_SOURCE_DIR}:/root:ro' \
--volume /sys/fs/cgroup:/sys/fs/cgroup:rw \
--tmpfs /tmp --tmpfs /run --tmpfs /run/lock \
${IMAGE} \
/usr/sbin/init"
)
set_tests_properties(
${PKG}_container_start
PROPERTIES FIXTURES_SETUP ${PKG}_container LABELS packaging
)
# Fixture: stop container
# On CI: always stop. Locally: leave running on failure for diagnosis.
add_test(
NAME ${PKG}_container_stop
COMMAND
sh -c
"if [ -n \"$CI\" ] || ! docker exec xrpld_${PKG}_install_test test -f /tmp/test_failed 2>/dev/null; then \
docker rm -f xrpld_${PKG}_install_test; \
else \
echo 'Tests failed — leaving xrpld_${PKG}_install_test running for diagnosis'; \
echo 'Clean up with: docker rm -f xrpld_${PKG}_install_test'; \
fi"
)
set_tests_properties(
${PKG}_container_stop
PROPERTIES FIXTURES_CLEANUP ${PKG}_container LABELS packaging
)
# Install package and run smoke test
add_test(
NAME ${PKG}_install
COMMAND
docker exec -w /root xrpld_${PKG}_install_test bash
/root/package/test/smoketest.sh local
)
set_tests_properties(
${PKG}_install
PROPERTIES
FIXTURES_REQUIRED ${PKG}_container
FIXTURES_SETUP ${PKG}_installed
LABELS packaging
TIMEOUT 600
)
# Validate install paths and compat symlinks
add_test(
NAME ${PKG}_install_paths
COMMAND
docker exec -w /root xrpld_${PKG}_install_test sh
/root/package/test/check_install_paths.sh
)
set_tests_properties(
${PKG}_install_paths
PROPERTIES
FIXTURES_REQUIRED "${PKG}_container;${PKG}_installed"
LABELS packaging
TIMEOUT 60
)
endforeach()

View File

@@ -140,28 +140,6 @@ function(setup_protocol_autogen)
)
endif()
# Check pip index URL configuration
execute_process(
COMMAND ${VENV_PIP} config get global.index-url
OUTPUT_VARIABLE PIP_INDEX_URL
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
# Default PyPI URL
set(DEFAULT_PIP_INDEX "https://pypi.org/simple")
# Show warning if using non-default index
if(PIP_INDEX_URL AND NOT PIP_INDEX_URL STREQUAL "")
if(NOT PIP_INDEX_URL STREQUAL DEFAULT_PIP_INDEX)
message(
WARNING
"Private pip index URL detected: ${PIP_INDEX_URL}\n"
"You may need to connect to VPN to access this URL."
)
endif()
endif()
message(STATUS "Installing Python dependencies...")
execute_process(
COMMAND ${VENV_PIP} install --upgrade pip

View File

@@ -1,16 +1,16 @@
{
"version": "0.5",
"requires": [
"zlib/1.3.1#cac0f6daea041b0ccf42934163defb20%1774439233.809",
"zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76%1765850150.075",
"xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1765850149.987",
"sqlite3/3.51.0#66aa11eabd0e34954c5c1c061ad44abe%1763899256.358",
"soci/4.0.3#fe32b9ad5eb47e79ab9e45a68f363945%1774450067.231",
"sqlite3/3.49.1#8631739a4c9b93bd3d6b753bac548a63%1765850149.926",
"soci/4.0.3#a9f8d773cd33e356b5879a4b0564f287%1765850149.46",
"snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1765850147.878",
"secp256k1/0.7.1#481881709eb0bdd0185a12b912bbe8ad%1770910500.329",
"secp256k1/0.7.1#3a61e95e220062ef32c48d019e9c81f7%1770306721.686",
"rocksdb/10.5.1#4a197eca381a3e5ae8adf8cffa5aacd0%1765850186.86",
"re2/20251105#8579cfd0bda4daf0683f9e3898f964b4%1774398111.888",
"protobuf/6.33.5#d96d52ba5baaaa532f47bda866ad87a5%1773224203.27",
"openssl/3.6.1#e6399de266349245a4542fc5f6c71552%1774458290.139",
"re2/20230301#ca3b241baec15bd31ea9187150e0b333%1765850148.103",
"protobuf/6.32.1#f481fd276fc23a33b85a3ed1e898b693%1765850161.038",
"openssl/3.5.5#05a4ac5b7323f7a329b2db1391d9941f%1769599205.414",
"nudb/2.0.9#0432758a24204da08fee953ec9ea03cb%1769436073.32",
"lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1765850143.914",
"libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1765842973.492",
@@ -18,26 +18,27 @@
"libarchive/3.8.1#ffee18995c706e02bf96e7a2f7042e0d%1765850144.736",
"jemalloc/5.3.0#e951da9cf599e956cebc117880d2d9f8%1729241615.244",
"gtest/1.17.0#5224b3b3ff3b4ce1133cbdd27d53ee7d%1768312129.152",
"grpc/1.78.1#b1a9e74b145cc471bed4dc64dc6eb2c1%1772623605.068",
"grpc/1.72.0#f244a57bff01e708c55a1100b12e1589%1765850193.734",
"ed25519/2015.03#ae761bdc52730a843f0809bdf6c1b1f6%1765850143.772",
"date/3.0.4#862e11e80030356b53c2c38599ceb32b%1765850143.772",
"c-ares/1.34.6#545240bb1c40e2cacd4362d6b8967650%1774439234.681",
"c-ares/1.34.5#5581c2b62a608b40bb85d965ab3ec7c8%1765850144.336",
"bzip2/1.0.8#c470882369c2d95c5c77e970c0c7e321%1765850143.837",
"boost/1.90.0#d5e8defe7355494953be18524a7f135b%1769454080.269",
"abseil/20250127.0#bb0baf1f362bc4a725a24eddd419b8f7%1774365460.196"
"abseil/20250127.0#99262a368bd01c0ccca8790dfced9719%1766517936.993"
],
"build_requires": [
"zlib/1.3.1#cac0f6daea041b0ccf42934163defb20%1774439233.809",
"strawberryperl/5.32.1.1#8d114504d172cfea8ea1662d09b6333e%1774447376.964",
"protobuf/6.33.5#d96d52ba5baaaa532f47bda866ad87a5%1773224203.27",
"zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76%1765850150.075",
"strawberryperl/5.32.1.1#707032463aa0620fa17ec0d887f5fe41%1765850165.196",
"protobuf/6.32.1#f481fd276fc23a33b85a3ed1e898b693%1765850161.038",
"nasm/2.16.01#31e26f2ee3c4346ecd347911bd126904%1765850144.707",
"msys2/cci.latest#d22fe7b2808f5fd34d0a7923ace9c54f%1770657326.649",
"m4/1.4.19#5d7a4994e5875d76faf7acf3ed056036%1774365463.87",
"cmake/4.3.0#b939a42e98f593fb34d3a8c5cc860359%1774439249.183",
"b2/5.4.2#ffd6084a119587e70f11cd45d1a386e2%1774439233.447",
"msys2/cci.latest#eea83308ad7e9023f7318c60d5a9e6cb%1770199879.083",
"m4/1.4.19#70dc8bbb33e981d119d2acc0175cf381%1763158052.846",
"cmake/4.2.0#ae0a44f44a1ef9ab68fd4b3e9a1f8671%1765850153.937",
"cmake/3.31.10#313d16a1aa16bbdb2ca0792467214b76%1765850153.479",
"b2/5.3.3#107c15377719889654eb9a162a673975%1765850144.355",
"automake/1.16.5#b91b7c384c3deaa9d535be02da14d04f%1755524470.56",
"autoconf/2.71#51077f068e61700d65bb05541ea1e4b0%1731054366.86",
"abseil/20250127.0#bb0baf1f362bc4a725a24eddd419b8f7%1774365460.196"
"abseil/20250127.0#99262a368bd01c0ccca8790dfced9719%1766517936.993"
],
"python_requires": [],
"overrides": {
@@ -45,14 +46,14 @@
null,
"boost/1.90.0"
],
"protobuf/[>=5.27.0 <7]": [
"protobuf/6.33.5"
"protobuf/5.27.0": [
"protobuf/6.32.1"
],
"lz4/1.9.4": [
"lz4/1.10.0"
],
"sqlite3/[>=3.44 <4]": [
"sqlite3/3.51.0"
"sqlite3/3.44.2": [
"sqlite3/3.49.1"
],
"boost/1.83.0": [
"boost/1.90.0"

View File

@@ -1,9 +1,10 @@
import os
import re
import os
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
from conan import ConanFile
from conan import __version__ as conan_version
class Xrpl(ConanFile):
@@ -29,10 +30,10 @@ class Xrpl(ConanFile):
requires = [
"ed25519/2015.03",
"grpc/1.78.1",
"grpc/1.72.0",
"libarchive/3.8.1",
"nudb/2.0.9",
"openssl/3.6.1",
"openssl/3.5.5",
"secp256k1/0.7.1",
"soci/4.0.3",
"zlib/1.3.1",
@@ -43,7 +44,7 @@ class Xrpl(ConanFile):
]
tool_requires = [
"protobuf/6.33.5",
"protobuf/6.32.1",
]
default_options = {
@@ -136,16 +137,20 @@ class Xrpl(ConanFile):
self.default_options["fPIC"] = False
def requirements(self):
self.requires("boost/1.90.0", force=True, transitive_headers=True)
self.requires("date/3.0.4", transitive_headers=True)
# Conan 2 requires transitive headers to be specified
transitive_headers_opt = (
{"transitive_headers": True} if conan_version.split(".")[0] == "2" else {}
)
self.requires("boost/1.90.0", force=True, **transitive_headers_opt)
self.requires("date/3.0.4", **transitive_headers_opt)
self.requires("lz4/1.10.0", force=True)
self.requires("protobuf/6.33.5", force=True)
self.requires("sqlite3/3.51.0", force=True)
self.requires("protobuf/6.32.1", force=True)
self.requires("sqlite3/3.49.1", force=True)
if self.options.jemalloc:
self.requires("jemalloc/5.3.0")
if self.options.rocksdb:
self.requires("rocksdb/10.5.1")
self.requires("xxhash/0.8.3", transitive_headers=True)
self.requires("xxhash/0.8.3", **transitive_headers_opt)
exports_sources = (
"CMakeLists.txt",

View File

@@ -93,11 +93,14 @@ words:
- desync
- desynced
- determ
- disablerepo
- distro
- doxyfile
- dxrpl
- enablerepo
- endmacro
- exceptioned
- EXPECT_STREQ
- Falco
- fcontext
- finalizers
@@ -151,6 +154,7 @@ words:
- Merkle
- Metafuncton
- misprediction
- missingok
- mptbalance
- MPTDEX
- mptflags
@@ -181,7 +185,9 @@ words:
- NOLINT
- NOLINTNEXTLINE
- nonxrp
- noreplace
- noripple
- notifempty
- nudb
- nullptr
- nunl
@@ -201,6 +207,7 @@ words:
- preauthorize
- preauthorizes
- preclaim
- preun
- protobuf
- protos
- ptrs
@@ -235,12 +242,14 @@ words:
- sfields
- shamap
- shamapitem
- shlibs
- sidechain
- SIGGOOD
- sle
- sles
- soci
- socidb
- SRPMS
- sslws
- statsd
- STATSDCOLLECTOR
@@ -268,8 +277,8 @@ words:
- txn
- txns
- txs
- UBSAN
- ubsan
- UBSAN
- umant
- unacquired
- unambiguity
@@ -297,7 +306,6 @@ words:
- venv
- vfalco
- vinnie
- wasmi
- wextra
- wptr
- writeme
@@ -306,7 +314,6 @@ words:
- xbridge
- xchain
- ximinez
- EXPECT_STREQ
- XMACRO
- xrpkuwait
- xrpl

View File

@@ -109,32 +109,3 @@ Install CMake with Homebrew too:
```
brew install cmake
```
## Clang-tidy
Clang-tidy is required to run static analysis checks locally (see [CONTRIBUTING.md](../../CONTRIBUTING.md)).
It is not required to build the project. Currently this project uses clang-tidy version 21.
### Linux
LLVM 21 is not available in the default Debian 12 (Bookworm) repositories.
Install it using the official LLVM apt installer:
```
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 21
sudo apt install --yes clang-tidy-21
```
Then use `run-clang-tidy-21` when running clang-tidy locally.
### macOS
Install LLVM 21 via Homebrew:
```
brew install llvm@21
```
Then use `run-clang-tidy` from the LLVM 21 Homebrew prefix when running clang-tidy locally.

View File

@@ -45,7 +45,7 @@ class NetworkIDService;
class OpenLedger;
class OrderBookDB;
class Overlay;
class PathRequestManager;
class PathRequests;
class PeerReservationTable;
class PendingSaves;
class RelationalDatabase;
@@ -195,8 +195,8 @@ public:
virtual TxQ&
getTxQ() = 0;
virtual PathRequestManager&
getPathRequestManager() = 0;
virtual PathRequests&
getPathRequests() = 0;
// Server services
virtual ServerHandler&

View File

@@ -4,10 +4,6 @@
namespace xrpl {
// Deprecated constant for backwards compatibility with pre-XRPFees amendment.
// This was the reference fee units used in the old fee calculation.
inline constexpr std::uint32_t FEE_UNITS_DEPRECATED = 10;
/** Reflects the fee settings for a particular ledger.
The fees are always the same for any transactions applied
@@ -15,25 +11,15 @@ inline constexpr std::uint32_t FEE_UNITS_DEPRECATED = 10;
*/
struct Fees
{
/** @brief Cost of a reference transaction in drops. */
XRPAmount base{0};
/** @brief Minimum XRP an account must hold to exist on the ledger. */
XRPAmount reserve{0};
/** @brief Additional XRP reserve required per owned ledger object. */
XRPAmount increment{0};
XRPAmount base{0}; // Reference tx cost (drops)
XRPAmount reserve{0}; // Reserve base (drops)
XRPAmount increment{0}; // Reserve increment (drops)
explicit Fees() = default;
Fees(Fees const&) = default;
Fees&
operator=(Fees const&) = default;
Fees(XRPAmount base_, XRPAmount reserve_, XRPAmount increment_)
: base(base_), reserve(reserve_), increment(increment_)
{
}
/** Returns the account reserve given the owner count, in drops.
The reserve is calculated as the reserve base plus

View File

@@ -72,8 +72,4 @@ deserializeHeader(Slice data, bool hasHash = false);
LedgerHeader
deserializePrefixedHeader(Slice data, bool hasHash = false);
/** Calculate the hash of a ledger header. */
uint256
calculateLedgerHash(LedgerHeader const& info);
} // namespace xrpl

View File

@@ -16,7 +16,6 @@
// Add new amendments to the top of this list.
// Keep it sorted in reverse chronological order.
XRPL_FIX (Security3_1_3, Supported::no, VoteBehavior::DefaultNo)
XRPL_FIX (PermissionedDomainInvariant, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (ExpiredNFTokenOfferRemoval, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (BatchInnerSigs, Supported::no, VoteBehavior::DefaultNo)

118
package/README.md Normal file
View File

@@ -0,0 +1,118 @@
# Linux Packaging
This directory contains all files needed to build RPM and Debian packages for `xrpld`.
## Directory layout
```
package/
build_pkg.sh Staging and build script (called by CMake targets and CI)
rpm/
xrpld.spec.in RPM spec template (substitutes @xrpld_version@, @pkg_release@)
deb/
debian/ Debian control files (control, rules, install, links, conffiles, ...)
shared/
xrpld.service systemd unit file (used by both RPM and DEB)
xrpld.sysusers sysusers.d config (used by both RPM and DEB)
xrpld.tmpfiles tmpfiles.d config (used by both RPM and DEB)
xrpld.logrotate logrotate config (installed to /opt/xrpld/bin/, user activates)
update-xrpld.sh auto-update script (installed to /opt/xrpld/bin/)
update-xrpld-cron cron entry for auto-update (installed to /opt/xrpld/bin/)
test/
smoketest.sh Package install smoke test
check_install_paths.sh Verify install paths and compat symlinks
```
## Prerequisites
| Package type | Container | Tool required |
| ------------ | -------------------------------------- | --------------------------------------------------------------- |
| RPM | `ghcr.io/xrplf/ci/rhel-9:gcc-12` | `rpmbuild` |
| DEB | `ghcr.io/xrplf/ci/ubuntu-jammy:gcc-12` | `dpkg-buildpackage`, `debhelper (>= 13)`, `dh-sequence-systemd` |
## Building packages
### Via CI (recommended)
The `reusable-package.yml` workflow downloads a pre-built `xrpld` binary artifact
and calls `build_pkg.sh` directly. No CMake configure or build step is needed in
the packaging job.
### Via CMake (local development)
Configure with the required install prefix, then invoke the target:
```bash
cmake \
-DCMAKE_INSTALL_PREFIX=/opt/xrpld \
-Dxrpld=ON \
-Dtests=OFF \
..
# RPM (in RHEL container):
cmake --build . --target package-rpm
# DEB (in Debian/Ubuntu container):
cmake --build . --target package-deb
```
The `cmake/XrplPackaging.cmake` module gates each target on whether the required
tool (`rpmbuild` / `dpkg-buildpackage`) is present at configure time, so
configuring on a host that lacks one simply omits the corresponding target.
`CMAKE_INSTALL_PREFIX` must be `/opt/xrpld`; if it is not, both targets are
skipped with a `STATUS` message.
## How `build_pkg.sh` works
`build_pkg.sh <pkg_type> <src_dir> <build_dir> [version] [pkg_release]` stages
all files and invokes the platform build tool. It resolves `src_dir` and
`build_dir` to absolute paths, then calls `stage_common()` to copy the binary,
config files, and shared support files into the staging area.
### RPM
1. Creates the standard `rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}` tree inside the build directory.
2. Copies the generated `xrpld.spec` and all source files (binary, configs, service files) into `SOURCES/`.
3. Runs `rpmbuild -bb`. The spec uses manual `install` commands to place files.
4. Output: `rpmbuild/RPMS/x86_64/xrpld-*.rpm`
### DEB
1. Creates a staging source tree at `debbuild/source/` inside the build directory.
2. Stages the binary, configs, `README.md`, and `LICENSE.md`.
3. Copies `package/deb/debian/` control files into `debbuild/source/debian/`.
4. Copies shared service/sysusers/tmpfiles into `debian/` where `dh_installsystemd`, `dh_installsysusers`, and `dh_installtmpfiles` pick them up automatically.
5. Generates a minimal `debian/changelog` (pre-release versions use `~` instead of `-`).
6. Runs `dpkg-buildpackage -b --no-sign`. `debian/rules` uses manual `install` commands.
7. Output: `debbuild/*.deb` and `debbuild/*.ddeb` (dbgsym package)
## Post-build verification
```bash
# DEB
dpkg-deb -c debbuild/*.deb | grep -E 'systemd|sysusers|tmpfiles'
lintian -I debbuild/*.deb
# RPM
rpm -qlp rpmbuild/RPMS/x86_64/*.rpm
```
## Reproducibility
The following environment variables improve build reproducibility. They are not
set automatically by `build_pkg.sh`; set them manually if needed:
```bash
export SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct)
export TZ=UTC
export LC_ALL=C.UTF-8
export GZIP=-n
export DEB_BUILD_OPTIONS="noautodbgsym reproducible=+fixfilepath"
```
## TODO
- Port debsigs signing instructions and integrate into CI.
- Port RPM GPG signing setup (key import + `%{?_gpg_sign}` in spec).
- Introduce a virtual package for key rotation.

91
package/build_pkg.sh Executable file
View File

@@ -0,0 +1,91 @@
#!/usr/bin/env bash
# Build an RPM or Debian package from a pre-built xrpld binary.
#
# Usage: build_pkg.sh <pkg_type> <src_dir> <build_dir> [version] [pkg_release]
# pkg_type : rpm | deb
# src_dir : path to repository root
# build_dir : directory containing the pre-built xrpld binary
# version : package version string (e.g. 2.4.0-b1)
# pkg_release : package release number (default: 1)
set -euo pipefail
PKG_TYPE="${1:?pkg_type required}"
SRC_DIR="$(cd "${2:?src_dir required}" && pwd)"
BUILD_DIR="$(cd "${3:?build_dir required}" && pwd)"
VERSION="${4:-1.0.0}"
PKG_RELEASE="${5:-1}"
SHARED="${SRC_DIR}/package/shared"
# Stage files common to both package types into a target directory.
stage_common() {
local dest="$1"
cp "${BUILD_DIR}/xrpld" "${dest}/xrpld"
cp "${SRC_DIR}/cfg/xrpld-example.cfg" "${dest}/xrpld.cfg"
cp "${SRC_DIR}/cfg/validators-example.txt" "${dest}/validators.txt"
cp "${SHARED}/xrpld.logrotate" "${dest}/xrpld.logrotate"
cp "${SHARED}/update-xrpld.sh" "${dest}/update-xrpld.sh"
cp "${SHARED}/update-xrpld-cron" "${dest}/update-xrpld-cron"
}
build_rpm() {
local topdir="${BUILD_DIR}/rpmbuild"
mkdir -p "${topdir}"/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}
cp "${BUILD_DIR}/package/rpm/xrpld.spec" "${topdir}/SPECS/xrpld.spec"
stage_common "${topdir}/SOURCES"
cp "${SHARED}/xrpld.service" "${topdir}/SOURCES/xrpld.service"
cp "${SHARED}/xrpld.sysusers" "${topdir}/SOURCES/xrpld.sysusers"
cp "${SHARED}/xrpld.tmpfiles" "${topdir}/SOURCES/xrpld.tmpfiles"
set -x
rpmbuild -bb \
--define "_topdir ${topdir}" \
"${topdir}/SPECS/xrpld.spec"
}
build_deb() {
local staging="${BUILD_DIR}/debbuild/source"
rm -rf "${staging}"
mkdir -p "${staging}"
stage_common "${staging}"
cp "${SRC_DIR}/README.md" "${staging}/"
cp "${SRC_DIR}/LICENSE.md" "${staging}/"
# debian/ control files
cp -r "${SRC_DIR}/package/deb/debian" "${staging}/debian"
# Shared support files for dh_installsystemd / sysusers / tmpfiles
cp "${SHARED}/xrpld.service" "${staging}/debian/xrpld.service"
cp "${SHARED}/xrpld.sysusers" "${staging}/debian/xrpld.sysusers"
cp "${SHARED}/xrpld.tmpfiles" "${staging}/debian/xrpld.tmpfiles"
# Generate debian/changelog (pre-release versions use ~ instead of -).
local deb_version="${VERSION//-/\~}"
# TODO: Add facility for generating the changelog
cat > "${staging}/debian/changelog" <<EOF
xrpld (${deb_version}-${PKG_RELEASE}) unstable; urgency=medium
* Release ${VERSION}.
-- XRPL Foundation <contact@xrplf.org> $(LC_ALL=C date -u -R)
EOF
chmod +x "${staging}/debian/rules"
set -x
cd "${staging}"
dpkg-buildpackage -b --no-sign -d
}
case "${PKG_TYPE}" in
rpm) build_rpm ;;
deb) build_deb ;;
*)
echo "Unknown package type: ${PKG_TYPE}" >&2
exit 1
;;
esac

View File

@@ -0,0 +1,33 @@
Source: xrpld
Section: net
Priority: optional
Maintainer: XRPL Foundation <contact@xrpl.org>
Rules-Requires-Root: no
Build-Depends:
debhelper-compat (= 13),
Standards-Version: 4.7.0
Homepage: https://github.com/XRPLF/rippled
Vcs-Git: https://github.com/XRPLF/rippled.git
Vcs-Browser: https://github.com/XRPLF/rippled
Package: xrpld
Section: net
Priority: optional
Architecture: any
Depends:
${shlibs:Depends},
${misc:Depends}
Description: XRP Ledger daemon
xrpld is the reference implementation of the XRP Ledger protocol.
It participates in the peer-to-peer XRP Ledger network, processes
transactions, and maintains the ledger database.
Package: rippled
Architecture: all
Section: oldlibs
Priority: optional
Depends: xrpld, ${misc:Depends}
Description: transitional package - use xrpld
The rippled package has been renamed to xrpld. This transitional
package ensures a smooth upgrade and can be safely removed after
xrpld is installed.

View File

@@ -0,0 +1,20 @@
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: rippled
Source: https://github.com/XRPLF/rippled
Files: *
Copyright: 2012-2025 Ripple Labs Inc.
License: ISC
License: ISC
Permission to use, copy, modify, and 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.

37
package/deb/debian/rules Normal file
View File

@@ -0,0 +1,37 @@
#!/usr/bin/make -f
export DH_VERBOSE = 1
export DH_OPTIONS = -v
%:
dh $@
override_dh_auto_configure override_dh_auto_build override_dh_auto_test:
@:
override_dh_auto_install:
install -Dm0755 xrpld debian/tmp/opt/xrpld/bin/xrpld
install -Dm0644 xrpld.cfg debian/tmp/opt/xrpld/etc/xrpld.cfg
install -Dm0644 validators.txt debian/tmp/opt/xrpld/etc/validators.txt
install -Dm0644 xrpld.logrotate debian/tmp/opt/xrpld/bin/xrpld.logrotate
install -Dm0755 update-xrpld.sh debian/tmp/opt/xrpld/bin/update-xrpld.sh
install -Dm0644 update-xrpld-cron debian/tmp/opt/xrpld/bin/update-xrpld-cron
install -Dm0644 README.md debian/tmp/usr/share/doc/xrpld/README.md
install -Dm0644 LICENSE.md debian/tmp/usr/share/doc/xrpld/LICENSE.md
override_dh_installsystemd:
dh_installsystemd
# see if this still works
# dh_installsystemd --no-start
override_dh_installsysusers:
dh_installsysusers
override_dh_installtmpfiles:
dh_installtmpfiles
override_dh_install:
dh_install
override_dh_dwz:
@:

View File

@@ -0,0 +1 @@
3.0 (quilt)

View File

@@ -0,0 +1,2 @@
/opt/xrpld/etc/xrpld.cfg
/opt/xrpld/etc/validators.txt

View File

@@ -0,0 +1,10 @@
opt/xrpld/bin/xrpld
opt/xrpld/bin/xrpld.logrotate
opt/xrpld/bin/update-xrpld.sh
opt/xrpld/bin/update-xrpld-cron
opt/xrpld/etc/xrpld.cfg
opt/xrpld/etc/validators.txt
usr/share/doc/xrpld/README.md
usr/share/doc/xrpld/LICENSE.md

View File

@@ -0,0 +1,13 @@
opt/xrpld/etc etc/opt/xrpld
opt/xrpld/bin/xrpld usr/bin/xrpld
## remove when "rippled" deprecated
opt/xrpld/bin/xrpld opt/xrpld/bin/rippled
opt/xrpld/bin/xrpld usr/bin/rippled
opt/xrpld/bin/xrpld usr/local/bin/rippled
opt/xrpld/etc/xrpld.cfg opt/xrpld/etc/rippled.cfg
var/log/xrpld var/log/rippled
var/lib/xrpld var/lib/rippled
opt/xrpld opt/ripple
etc/opt/xrpld etc/opt/ripple

113
package/rpm/xrpld.spec.in Normal file
View File

@@ -0,0 +1,113 @@
%global xrpld_version @xrpld_version@
%global pkg_release @pkg_release@
%global _opt_prefix /opt/xrpld
%global ver_base %(v=%{xrpld_version}; echo ${v%%-*})
%global _has_dash %(v=%{xrpld_version}; [ "${v#*-}" != "$v" ] && echo 1 || echo 0)
%if 0%{?_has_dash}
%global ver_suffix %(v=%{xrpld_version}; printf %s "${v#*-}")
%endif
Name: xrpld
Version: %{ver_base}
Release: %{?ver_suffix:0.%{ver_suffix}.}%{pkg_release}%{?dist}
Summary: XRP Ledger daemon
License: ISC
URL: https://github.com/XRPLF/rippled
Source0: xrpld
Source1: xrpld.cfg
Source2: validators.txt
Source3: xrpld.service
Source4: xrpld.sysusers
Source5: xrpld.tmpfiles
Source6: xrpld.logrotate
Source7: update-xrpld.sh
Source8: update-xrpld-cron
BuildArch: x86_64
BuildRequires: systemd-rpm-macros
%undefine _debugsource_packages
%debug_package
%{?systemd_requires}
%{?sysusers_requires_compat}
%description
xrpld is the reference implementation of the XRP Ledger protocol. It
participates in the peer-to-peer XRP Ledger network, processes
transactions, and maintains the ledger database.
%install
rm -rf %{buildroot}
# Suppress debugsource subpackage — no source files in the build tree.
touch %{_builddir}/debugsourcefiles.list
# Install binary and config files.
install -Dm0755 %{SOURCE0} %{buildroot}%{_opt_prefix}/bin/xrpld
install -Dm0644 %{SOURCE1} %{buildroot}%{_opt_prefix}/etc/xrpld.cfg
install -Dm0644 %{SOURCE2} %{buildroot}%{_opt_prefix}/etc/validators.txt
# Compatibility symlinks (matches debian/xrpld.links).
mkdir -p %{buildroot}/etc/opt %{buildroot}/usr/bin %{buildroot}/usr/local/bin \
%{buildroot}/var/log %{buildroot}/var/lib
ln -s %{_opt_prefix}/etc %{buildroot}/etc/opt/xrpld
ln -s %{_opt_prefix}/bin/xrpld %{buildroot}/usr/bin/xrpld
## remove when "rippled" deprecated
ln -s xrpld %{buildroot}%{_opt_prefix}/bin/rippled
ln -s %{_opt_prefix}/bin/xrpld %{buildroot}/usr/bin/rippled
ln -s %{_opt_prefix}/bin/xrpld %{buildroot}/usr/local/bin/rippled
ln -s xrpld.cfg %{buildroot}%{_opt_prefix}/etc/rippled.cfg
ln -s %{_opt_prefix} %{buildroot}/opt/ripple
ln -s /etc/opt/xrpld %{buildroot}/etc/opt/ripple
ln -s xrpld %{buildroot}/var/log/rippled
ln -s xrpld %{buildroot}/var/lib/rippled
# Install systemd/sysusers/tmpfiles support files.
install -Dm0644 %{SOURCE3} %{buildroot}%{_unitdir}/xrpld.service
install -Dm0644 %{SOURCE4} %{buildroot}%{_sysusersdir}/xrpld.conf
install -Dm0644 %{SOURCE5} %{buildroot}%{_tmpfilesdir}/xrpld.conf
install -Dm0644 %{SOURCE6} %{buildroot}%{_opt_prefix}/bin/xrpld.logrotate
install -Dm0755 %{SOURCE7} %{buildroot}%{_opt_prefix}/bin/update-xrpld.sh
install -Dm0644 %{SOURCE8} %{buildroot}%{_opt_prefix}/bin/update-xrpld-cron
%pre
%sysusers_create_compat %{SOURCE4}
%post
%systemd_post xrpld.service
%preun
%systemd_preun xrpld.service
%postun
%systemd_postun_with_restart xrpld.service
%files
%dir %{_opt_prefix}
%dir %{_opt_prefix}/bin
%{_opt_prefix}/bin/xrpld
%{_opt_prefix}/bin/xrpld.logrotate
%{_opt_prefix}/bin/update-xrpld.sh
%{_opt_prefix}/bin/update-xrpld-cron
%{_opt_prefix}/bin/rippled
/usr/bin/xrpld
/usr/bin/rippled
/usr/local/bin/rippled
%dir %{_opt_prefix}/etc
%config(noreplace) %{_opt_prefix}/etc/xrpld.cfg
%config(noreplace) %{_opt_prefix}/etc/validators.txt
%{_opt_prefix}/etc/rippled.cfg
/etc/opt/xrpld
/etc/opt/ripple
/opt/ripple
%{_unitdir}/xrpld.service
%{_sysusersdir}/xrpld.conf
%{_tmpfilesdir}/xrpld.conf
/var/log/rippled
/var/lib/rippled
%ghost %dir /var/opt/ripple
%ghost %dir /var/opt/ripple/lib
%ghost %dir /var/opt/ripple/log

View File

@@ -0,0 +1,9 @@
# For automatic updates, symlink this file to /etc/cron.d/
# Do not remove the newline at the end of this cron script
# bash required for use of RANDOM below.
SHELL=/bin/bash
PATH=/sbin;/bin;/usr/sbin;/usr/bin
# invoke check/update script with random delay up to 59 mins
0 * * * * root sleep $((RANDOM*3540/32768)) && /opt/xrpld/bin/update-xrpld.sh

64
package/shared/update-xrpld.sh Executable file
View File

@@ -0,0 +1,64 @@
#!/usr/bin/env bash
# auto-update script for xrpld daemon
# Check for sudo/root permissions
if [[ $(id -u) -ne 0 ]] ; then
echo "This update script must be run as root or sudo"
exit 1
fi
LOCKDIR=/tmp/xrpld-update.lock
UPDATELOG=/var/log/xrpld/update.log
function cleanup {
# If this directory isn't removed, future updates will fail.
rmdir $LOCKDIR
}
# Use mkdir to check if process is already running. mkdir is atomic, as against file create.
if ! mkdir $LOCKDIR 2>/dev/null; then
echo $(date -u) "lockdir exists - won't proceed." >> $UPDATELOG
exit 1
fi
trap cleanup EXIT
source /etc/os-release
can_update=false
if [[ "$ID" == "ubuntu" || "$ID" == "debian" ]] ; then
# Silent update
apt-get update -qq
# The next line is an "awk"ward way to check if the package needs to be updated.
XRPLD=$(apt-get install -s --only-upgrade xrpld | awk '/^Inst/ { print $2 }')
test "$XRPLD" == "xrpld" && can_update=true
function apply_update {
apt-get install xrpld -qq
}
elif [[ "$ID" == "fedora" || "$ID" == "centos" || "$ID" == "rhel" || "$ID" == "scientific" ]] ; then
RIPPLE_REPO=${RIPPLE_REPO-stable}
yum --disablerepo=* --enablerepo=ripple-$RIPPLE_REPO clean expire-cache
yum check-update -q --enablerepo=ripple-$RIPPLE_REPO xrpld || can_update=true
function apply_update {
yum update -y --enablerepo=ripple-$RIPPLE_REPO xrpld
}
else
echo "unrecognized distro!"
exit 1
fi
# Do the actual update and restart the service after reloading systemctl daemon.
if [ "$can_update" = true ] ; then
exec 3>&1 1>>${UPDATELOG} 2>&1
set -e
apply_update
systemctl daemon-reload
systemctl restart xrpld.service
echo $(date -u) "xrpld daemon updated."
else
echo $(date -u) "no updates available" >> $UPDATELOG
fi

View File

@@ -0,0 +1,15 @@
/var/log/xrpld/*.log {
daily
minsize 200M
rotate 7
nocreate
missingok
notifempty
compress
compresscmd /usr/bin/nice
compressoptions -n19 ionice -c3 gzip
compressext .gz
postrotate
/opt/xrpld/bin/xrpld --conf /etc/opt/xrpld/xrpld.cfg logrotate
endscript
}

View File

@@ -0,0 +1,15 @@
[Unit]
Description=XRP Ledger Daemon
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/opt/xrpld/bin/xrpld --net --silent --conf /etc/opt/xrpld/xrpld.cfg
Restart=on-failure
User=xrpld
Group=xrpld
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1 @@
u xrpld - "XRP Ledger daemon" /var/lib/xrpld /sbin/nologin

View File

@@ -0,0 +1,2 @@
d /var/opt/ripple/lib 0750 xrpld xrpld -
d /var/opt/ripple/log 0750 xrpld xrpld -

View File

@@ -0,0 +1,50 @@
#!/usr/bin/env sh
# Validate installed paths and compat symlinks for xrpld packages.
set -e
set -x
trap 'test $? -ne 0 && touch /tmp/test_failed' EXIT
check() { test $1 "$2" || { echo "FAIL: $1 $2"; exit 1; }; }
check_resolves_to() {
actual=$(readlink -f "$1")
[ "$actual" = "$2" ] || { echo "FAIL: $1 resolves to $actual, expected $2"; exit 1; }
}
# var dirs (compat symlinks)
check -L /var/log/rippled
check -L /var/lib/rippled
# compat directory symlinks — existence and resolved target
check -L /opt/ripple
check_resolves_to /opt/ripple /opt/xrpld
check -L /etc/opt/xrpld
check_resolves_to /etc/opt/xrpld /opt/xrpld/etc
check -L /etc/opt/ripple
check_resolves_to /etc/opt/ripple /opt/xrpld/etc
# config accessible via all expected paths
check -f /opt/xrpld/etc/xrpld.cfg
check -f /opt/xrpld/etc/rippled.cfg
check -f /etc/opt/xrpld/xrpld.cfg
check -f /etc/opt/xrpld/rippled.cfg
check -f /etc/opt/ripple/xrpld.cfg
check -f /etc/opt/ripple/rippled.cfg
if systemctl is-system-running >/dev/null 2>&1; then
# service file sanity check
SERVICE=$(systemctl cat xrpld)
echo "$SERVICE" | grep -q 'ExecStart=/opt/xrpld/bin/xrpld' || { echo "FAIL: ExecStart wrong"; echo "$SERVICE"; exit 1; }
echo "$SERVICE" | grep -q 'User=xrpld' || { echo "FAIL: User not xrpld"; echo "$SERVICE"; exit 1; }
fi
# binary accessible via all expected paths
/opt/xrpld/bin/xrpld --version
/opt/xrpld/bin/rippled --version
/opt/ripple/bin/xrpld --version
/opt/ripple/bin/rippled --version
/usr/bin/xrpld --version
/usr/bin/rippled --version
/usr/local/bin/rippled --version

76
package/test/smoketest.sh Executable file
View File

@@ -0,0 +1,76 @@
#!/usr/bin/env bash
# Install a locally-built package and run basic verification.
#
# Usage: smoketest.sh local
# Expects packages in build/{dpkg,rpm}/packages/ or build/debbuild/ / build/rpmbuild/RPMS/
set -x
trap 'test $? -ne 0 && touch /tmp/test_failed' EXIT
install_from=$1
. /etc/os-release
case ${ID} in
ubuntu|debian)
pkgtype="dpkg"
;;
fedora|centos|rhel|rocky|almalinux)
pkgtype="rpm"
;;
*)
echo "unrecognized distro!"
exit 1
;;
esac
if [ "${install_from}" != "local" ]; then
echo "only 'local' install mode is supported"
exit 1
fi
# Install the package
if [ "${pkgtype}" = "dpkg" ] ; then
apt-get -y update
# Find .deb files — check both possible output locations
debs=$(find build/debbuild/ build/dpkg/packages/ -name '*.deb' ! -name '*dbgsym*' 2>/dev/null | head -5)
if [ -z "$debs" ]; then
echo "No .deb files found"
exit 1
fi
dpkg --no-debsig -i $debs || apt-get -y install -f
elif [ "${pkgtype}" = "rpm" ] ; then
# Find .rpm files — check both possible output locations
rpms=$(find build/rpmbuild/RPMS/ build/rpm/packages/ -name '*.rpm' \
! -name '*debug*' ! -name '*devel*' ! -name '*.src.rpm' 2>/dev/null | head -5)
if [ -z "$rpms" ]; then
echo "No .rpm files found"
exit 1
fi
rpm -i $rpms
fi
# Verify installed version
VERSION_OUTPUT=$(/opt/xrpld/bin/xrpld --version)
INSTALLED=$(echo "$VERSION_OUTPUT" | head -1 | awk '{print $NF}')
echo "Installed version: ${INSTALLED}"
# Run unit tests
if [ -n "${CI:-}" ]; then
unittest_jobs=$(nproc)
else
unittest_jobs=16
fi
cd /tmp
/opt/xrpld/bin/xrpld --unittest --unittest-jobs ${unittest_jobs} > /tmp/unittest_results || true
cd -
num_failures=$(tail /tmp/unittest_results -n1 | grep -oP '\d+(?= failures)')
if [ "${num_failures:-0}" -ne 0 ]; then
echo "$num_failures unit test(s) failed:"
grep 'failed:' /tmp/unittest_results
exit 1
fi
# Compat path checks
"$(dirname "${BASH_SOURCE[0]}")/check_install_paths.sh"

View File

@@ -433,7 +433,8 @@ doWithdraw(
j) < amount)
{
// LCOV_EXCL_START
JLOG(j.error()) << "doWithdraw: negative balance of broker cover assets.";
JLOG(j.error()) << "LoanBrokerCoverWithdraw: negative balance of "
"broker cover assets.";
return tefINTERNAL;
// LCOV_EXCL_STOP
}

View File

@@ -69,7 +69,7 @@ forEachItem(
for (auto const& key : sle->getFieldV256(sfIndexes))
f(view.read(keylet::child(key)));
auto const next = sle->getFieldU64(sfIndexNext);
if (next == 0u)
if (!next)
return;
pos = keylet::page(root, next);
}

View File

@@ -1,7 +1,6 @@
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
//
#include <xrpl/basics/Log.h>
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
@@ -13,6 +12,21 @@
namespace xrpl {
// Forward declarations for functions that remain in View.h/cpp
bool
isVaultPseudoAccountFrozen(
ReadView const& view,
AccountID const& account,
MPTIssue const& mptShare,
int depth);
[[nodiscard]] TER
dirLink(
ApplyView& view,
AccountID const& owner,
std::shared_ptr<SLE>& object,
SF_UINT64 const& node = sfOwnerNode);
bool
isGlobalFrozen(ReadView const& view, MPTIssue const& mptIssue)
{
@@ -69,7 +83,7 @@ transferRate(ReadView const& view, MPTID const& issuanceID)
// which represents 50% of 1,000,000,000
if (auto const sle = view.read(keylet::mptIssuance(issuanceID));
sle && sle->isFieldPresent(sfTransferFee))
return Rate{1'000'000'000u + (10'000 * sle->getFieldU16(sfTransferFee))};
return Rate{1'000'000'000u + 10'000 * sle->getFieldU16(sfTransferFee)};
return parityRate;
}
@@ -135,7 +149,7 @@ authorizeMPToken(
// When a holder wants to unauthorize/delete a MPT, the ledger must
// - delete mptokenKey from owner directory
// - delete the MPToken
if ((flags & tfMPTUnauthorize) != 0)
if (flags & tfMPTUnauthorize)
{
auto const mptokenKey = keylet::mptoken(mptIssuanceID, account);
auto const sleMpt = view.peek(mptokenKey);
@@ -215,7 +229,7 @@ authorizeMPToken(
// Issuer wants to unauthorize the holder, unset lsfMPTAuthorized on
// their MPToken
if ((flags & tfMPTUnauthorize) != 0)
if (flags & tfMPTUnauthorize)
{
flagsOut &= ~lsfMPTAuthorized;
}
@@ -476,7 +490,7 @@ canTransfer(
if (!sleIssuance)
return tecOBJECT_NOT_FOUND;
if (!sleIssuance->isFlag(lsfMPTCanTransfer))
if (!(sleIssuance->getFieldU32(sfFlags) & lsfMPTCanTransfer))
{
if (from != (*sleIssuance)[sfIssuer] && to != (*sleIssuance)[sfIssuer])
return TER{tecNO_AUTH};

View File

@@ -224,10 +224,10 @@ trustCreate(
bSetHigh ? sfLowLimit : sfHighLimit,
STAmount(Issue{saBalance.getCurrency(), bSetDst ? uSrcAccountID : uDstAccountID}));
if (uQualityIn != 0u)
if (uQualityIn)
sleRippleState->setFieldU32(bSetHigh ? sfHighQualityIn : sfLowQualityIn, uQualityIn);
if (uQualityOut != 0u)
if (uQualityOut)
sleRippleState->setFieldU32(bSetHigh ? sfHighQualityOut : sfLowQualityOut, uQualityOut);
std::uint32_t uFlags = bSetHigh ? lsfHighReserve : lsfLowReserve;
@@ -327,16 +327,16 @@ updateTrustLine(
// Sender balance was positive.
&& after <= beast::zero
// Sender is zero or negative.
&& ((flags & (!bSenderHigh ? lsfLowReserve : lsfHighReserve)) != 0u)
&& (flags & (!bSenderHigh ? lsfLowReserve : lsfHighReserve))
// Sender reserve is set.
&& static_cast<bool>(flags & (!bSenderHigh ? lsfLowNoRipple : lsfHighNoRipple)) !=
static_cast<bool>(sle->getFlags() & lsfDefaultRipple) &&
((flags & (!bSenderHigh ? lsfLowFreeze : lsfHighFreeze)) == 0u) &&
!(flags & (!bSenderHigh ? lsfLowFreeze : lsfHighFreeze)) &&
!state->getFieldAmount(!bSenderHigh ? sfLowLimit : sfHighLimit)
// Sender trust limit is 0.
&& (state->getFieldU32(!bSenderHigh ? sfLowQualityIn : sfHighQualityIn) == 0u)
&& !state->getFieldU32(!bSenderHigh ? sfLowQualityIn : sfHighQualityIn)
// Sender quality in is 0.
&& (state->getFieldU32(!bSenderHigh ? sfLowQualityOut : sfHighQualityOut) == 0u))
&& !state->getFieldU32(!bSenderHigh ? sfLowQualityOut : sfHighQualityOut))
// Sender quality out is 0.
{
// VFALCO Where is the line being deleted?
@@ -348,7 +348,7 @@ updateTrustLine(
// Balance is zero, receiver reserve is clear.
if (!after // Balance is zero.
&& ((flags & (bSenderHigh ? lsfLowReserve : lsfHighReserve)) == 0u))
&& !(flags & (bSenderHigh ? lsfLowReserve : lsfHighReserve)))
return true;
}
return false;
@@ -539,12 +539,11 @@ requireAuth(ReadView const& view, Issue const& issue, AccountID const& account,
// If this is a weak or legacy check, or if the account has a line, fail if
// auth is required and not set on the line
if (auto const issuerAccount = view.read(keylet::account(issue.account));
issuerAccount && (((*issuerAccount)[sfFlags] & lsfRequireAuth) != 0u))
issuerAccount && (*issuerAccount)[sfFlags] & lsfRequireAuth)
{
if (trustLine)
{
return (((*trustLine)[sfFlags] &
((account > issue.account) ? lsfLowAuth : lsfHighAuth)) != 0u)
return ((*trustLine)[sfFlags] & ((account > issue.account) ? lsfLowAuth : lsfHighAuth))
? tesSUCCESS
: TER{tecNO_AUTH};
}
@@ -576,7 +575,7 @@ canTransfer(ReadView const& view, Issue const& issue, AccountID const& from, Acc
bool const issuerHigh = issuerId > account;
return line->isFlag(issuerHigh ? lsfHighNoRipple : lsfLowNoRipple);
}
return !sleIssuer->isFlag(lsfDefaultRipple);
return sleIssuer->isFlag(lsfDefaultRipple) == false;
};
// Fail if rippling disabled on both trust lines
@@ -749,7 +748,7 @@ deleteAMMTrustLine(
}
auto const uFlags = !ammLow ? lsfLowReserve : lsfHighReserve;
if ((sleState->getFlags() & uFlags) == 0u)
if (!(sleState->getFlags() & uFlags))
return tecINTERNAL; // LCOV_EXCL_LINE
adjustOwnerCount(view, !ammLow ? sleLow : sleHigh, -1, j);

View File

@@ -570,18 +570,17 @@ rippleCreditIOU(
// Sender balance was positive.
&& saBalance <= beast::zero
// Sender is zero or negative.
&& ((uFlags & (!bSenderHigh ? lsfLowReserve : lsfHighReserve)) != 0u)
&& (uFlags & (!bSenderHigh ? lsfLowReserve : lsfHighReserve))
// Sender reserve is set.
&& static_cast<bool>(uFlags & (!bSenderHigh ? lsfLowNoRipple : lsfHighNoRipple)) !=
static_cast<bool>(
view.read(keylet::account(uSenderID))->getFlags() & lsfDefaultRipple) &&
((uFlags & (!bSenderHigh ? lsfLowFreeze : lsfHighFreeze)) == 0u) &&
!(uFlags & (!bSenderHigh ? lsfLowFreeze : lsfHighFreeze)) &&
!sleRippleState->getFieldAmount(!bSenderHigh ? sfLowLimit : sfHighLimit)
// Sender trust limit is 0.
&& (sleRippleState->getFieldU32(!bSenderHigh ? sfLowQualityIn : sfHighQualityIn) == 0u)
&& !sleRippleState->getFieldU32(!bSenderHigh ? sfLowQualityIn : sfHighQualityIn)
// Sender quality in is 0.
&&
(sleRippleState->getFieldU32(!bSenderHigh ? sfLowQualityOut : sfHighQualityOut) == 0u))
&& !sleRippleState->getFieldU32(!bSenderHigh ? sfLowQualityOut : sfHighQualityOut))
// Sender quality out is 0.
{
// Clear the reserve of the sender, possibly delete the line!
@@ -593,7 +592,7 @@ rippleCreditIOU(
// Balance is zero, receiver reserve is clear.
bDelete = !saBalance // Balance is zero.
&& ((uFlags & (bSenderHigh ? lsfLowReserve : lsfHighReserve)) == 0u);
&& !(uFlags & (bSenderHigh ? lsfLowReserve : lsfHighReserve));
// Receiver reserve is clear.
}

View File

@@ -92,7 +92,7 @@ sharesToAssetsWithdraw(
std::shared_ptr<SLE const> const& issuance,
STAmount const& shares)
{
XRPL_ASSERT(!shares.negative(), "xrpl::sharesToAssetsWithdraw : non-negative shares");
XRPL_ASSERT(!shares.negative(), "xrpl::sharesToAssetsDeposit : non-negative shares");
XRPL_ASSERT(
shares.asset() == vault->at(sfShareMPTID),
"xrpl::sharesToAssetsWithdraw : shares and vault match");

View File

@@ -23,7 +23,7 @@ namespace {
// and follow the format described at http://semver.org/
//------------------------------------------------------------------------------
// clang-format off
char const* const versionString = "3.2.0-b1"
char const* const versionString = "3.2.0-b0"
// clang-format on
;

View File

@@ -1,9 +1,7 @@
#include <xrpl/basics/Slice.h>
#include <xrpl/basics/chrono.h>
#include <xrpl/protocol/HashPrefix.h>
#include <xrpl/protocol/LedgerHeader.h>
#include <xrpl/protocol/Serializer.h>
#include <xrpl/protocol/digest.h>
namespace xrpl {
@@ -53,21 +51,4 @@ deserializePrefixedHeader(Slice data, bool hasHash)
return deserializeHeader(data + 4, hasHash);
}
uint256
calculateLedgerHash(LedgerHeader const& info)
{
// VFALCO This has to match addRaw in View.h.
return sha512Half(
HashPrefix::ledgerMaster,
std::uint32_t(info.seq),
std::uint64_t(info.drops.drops()),
info.parentHash,
info.txHash,
info.accountHash,
std::uint32_t(info.parentCloseTime.time_since_epoch().count()),
std::uint32_t(info.closeTime.time_since_epoch().count()),
std::uint8_t(info.closeTimeResolution.count()),
std::uint8_t(info.closeFlags));
}
} // namespace xrpl

View File

@@ -12,6 +12,8 @@ namespace xrpl {
Expected<std::vector<SignerEntries::SignerEntry>, NotTEC>
SignerEntries::deserialize(STObject const& obj, beast::Journal journal, std::string_view annotation)
{
std::pair<std::vector<SignerEntry>, NotTEC> s;
if (!obj.isFieldPresent(sfSignerEntries))
{
JLOG(journal.trace()) << "Malformed " << annotation << ": Need signer entry array.";

View File

@@ -677,7 +677,8 @@ Transactor::checkSign(
}
// Look up the account.
auto const idSigner = calcAccountID(PublicKey(makeSlice(pkSigner)));
auto const idSigner =
pkSigner.empty() ? idAccount : calcAccountID(PublicKey(makeSlice(pkSigner)));
auto const sleAccount = view.read(keylet::account(idAccount));
if (!sleAccount)
return terNO_ACCOUNT;

View File

@@ -100,6 +100,8 @@ PermissionedDomainSet::doApply()
Keylet const pdKeylet =
keylet::permissionedDomain(account_, ctx_.tx.getFieldU32(sfSequence));
auto slePd = std::make_shared<SLE>(pdKeylet);
if (!slePd)
return tefINTERNAL; // LCOV_EXCL_LINE
slePd->setAccountID(sfOwner, account_);
slePd->setFieldU32(sfSequence, ctx_.tx.getFieldU32(sfSequence));

View File

@@ -55,7 +55,7 @@ VaultDelete::preclaim(PreclaimContext const& ctx)
if (!sleMPT)
{
// LCOV_EXCL_START
JLOG(ctx.j.error()) << "VaultDelete: missing issuance of vault shares.";
JLOG(ctx.j.error()) << "VaultDeposit: missing issuance of vault shares.";
return tecOBJECT_NOT_FOUND;
// LCOV_EXCL_STOP
}
@@ -63,7 +63,7 @@ VaultDelete::preclaim(PreclaimContext const& ctx)
if (sleMPT->at(sfIssuer) != vault->getAccountID(sfAccount))
{
// LCOV_EXCL_START
JLOG(ctx.j.error()) << "VaultDelete: invalid owner of vault shares.";
JLOG(ctx.j.error()) << "VaultDeposit: invalid owner of vault shares.";
return tecNO_PERMISSION;
// LCOV_EXCL_STOP
}
@@ -200,6 +200,8 @@ VaultDelete::doApply()
// Destroy the vault.
view().erase(vault);
associateAsset(*vault, asset);
return tesSUCCESS;
}

View File

@@ -5,10 +5,11 @@
#include <test/jtx/amount.h>
#include <test/jtx/sendmax.h>
#include <xrpld/app/paths/AMMOffer.h>
#include <xrpl/ledger/PaymentSandbox.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/STParsedJSON.h>
#include <xrpl/tx/paths/AMMOffer.h>
#include <xrpl/tx/paths/Flow.h>
#include <xrpl/tx/paths/detail/StrandFlow.h>
#include <xrpl/tx/transactors/dex/AMMContext.h>

View File

@@ -1,5 +1,6 @@
#include <test/jtx.h>
#include <xrpld/app/ledger/Ledger.h>
#include <xrpld/app/misc/FeeVote.h>
#include <xrpl/basics/BasicConfig.h>
@@ -250,8 +251,7 @@ class FeeVote_test : public beast::unit_test::suite
jtx::Env env(*this, jtx::testable_amendments() - featureXRPFees);
auto ledger = std::make_shared<Ledger>(
create_genesis,
Rules{env.app().config().features},
env.app().config().FEES.toFees(),
env.app().config(),
std::vector<uint256>{},
env.app().getNodeFamily());
@@ -280,8 +280,7 @@ class FeeVote_test : public beast::unit_test::suite
jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees);
auto ledger = std::make_shared<Ledger>(
create_genesis,
Rules{env.app().config().features},
env.app().config().FEES.toFees(),
env.app().config(),
std::vector<uint256>{},
env.app().getNodeFamily());
@@ -313,8 +312,7 @@ class FeeVote_test : public beast::unit_test::suite
jtx::Env env(*this, jtx::testable_amendments() - featureXRPFees);
auto ledger = std::make_shared<Ledger>(
create_genesis,
Rules{env.app().config().features},
env.app().config().FEES.toFees(),
env.app().config(),
std::vector<uint256>{},
env.app().getNodeFamily());
@@ -335,8 +333,7 @@ class FeeVote_test : public beast::unit_test::suite
jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees);
auto ledger = std::make_shared<Ledger>(
create_genesis,
Rules{env.app().config().features},
env.app().config().FEES.toFees(),
env.app().config(),
std::vector<uint256>{},
env.app().getNodeFamily());
@@ -361,11 +358,7 @@ class FeeVote_test : public beast::unit_test::suite
jtx::Env env(*this, jtx::testable_amendments());
auto ledger = std::make_shared<Ledger>(
create_genesis,
Rules{env.app().config().features},
env.app().config().FEES.toFees(),
std::vector<uint256>{},
env.app().getNodeFamily());
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
// Create the next ledger to apply transaction to
ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
@@ -400,11 +393,7 @@ class FeeVote_test : public beast::unit_test::suite
jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees);
auto ledger = std::make_shared<Ledger>(
create_genesis,
Rules{env.app().config().features},
env.app().config().FEES.toFees(),
std::vector<uint256>{},
env.app().getNodeFamily());
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
@@ -448,11 +437,7 @@ class FeeVote_test : public beast::unit_test::suite
jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees);
auto ledger = std::make_shared<Ledger>(
create_genesis,
Rules{env.app().config().features},
env.app().config().FEES.toFees(),
std::vector<uint256>{},
env.app().getNodeFamily());
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
@@ -479,11 +464,7 @@ class FeeVote_test : public beast::unit_test::suite
jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees);
auto ledger = std::make_shared<Ledger>(
create_genesis,
Rules{env.app().config().features},
env.app().config().FEES.toFees(),
std::vector<uint256>{},
env.app().getNodeFamily());
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
@@ -525,11 +506,7 @@ class FeeVote_test : public beast::unit_test::suite
jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees);
auto ledger = std::make_shared<Ledger>(
create_genesis,
Rules{env.app().config().features},
env.app().config().FEES.toFees(),
std::vector<uint256>{},
env.app().getNodeFamily());
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
@@ -567,8 +544,7 @@ class FeeVote_test : public beast::unit_test::suite
auto ledger = std::make_shared<Ledger>(
create_genesis,
Rules{env.app().config().features},
env.app().config().FEES.toFees(),
env.app().config(),
std::vector<uint256>{},
env.app().getNodeFamily());
@@ -597,8 +573,7 @@ class FeeVote_test : public beast::unit_test::suite
auto ledger = std::make_shared<Ledger>(
create_genesis,
Rules{env.app().config().features},
env.app().config().FEES.toFees(),
env.app().config(),
std::vector<uint256>{},
env.app().getNodeFamily());
@@ -641,11 +616,7 @@ class FeeVote_test : public beast::unit_test::suite
auto feeVote = make_FeeVote(setup, env.app().journal("FeeVote"));
auto ledger = std::make_shared<Ledger>(
create_genesis,
Rules{env.app().config().features},
env.app().config().FEES.toFees(),
std::vector<uint256>{},
env.app().getNodeFamily());
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
// doVoting requires a flag ledger (every 256th ledger)
// We need to create a ledger at sequence 256 to make it a flag ledger

View File

@@ -38,8 +38,7 @@ public:
assert(!stx);
return std::make_shared<Ledger>(
create_genesis,
Rules{env.app().config().features},
env.app().config().FEES.toFees(),
env.app().config(),
std::vector<uint256>{},
env.app().getNodeFamily());
}

View File

@@ -1,10 +1,10 @@
#include <test/jtx.h>
#include <xrpld/app/consensus/RCLValidations.h>
#include <xrpld/app/ledger/Ledger.h>
#include <xrpl/basics/base_uint.h>
#include <xrpl/beast/unit_test.h>
#include <xrpl/ledger/Ledger.h>
namespace xrpl {
namespace test {
@@ -57,11 +57,7 @@ class RCLValidations_test : public beast::unit_test::suite
jtx::Env env(*this);
Config config;
auto prev = std::make_shared<Ledger const>(
create_genesis,
Rules{config.features},
config.FEES.toFees(),
std::vector<uint256>{},
env.app().getNodeFamily());
create_genesis, config, std::vector<uint256>{}, env.app().getNodeFamily());
history.push_back(prev);
for (auto i = 0; i < ((2 * maxAncestors) + 1); ++i)
{
@@ -223,11 +219,7 @@ class RCLValidations_test : public beast::unit_test::suite
auto& j = env.journal;
Config config;
auto prev = std::make_shared<Ledger const>(
create_genesis,
Rules{config.features},
config.FEES.toFees(),
std::vector<uint256>{},
env.app().getNodeFamily());
create_genesis, config, std::vector<uint256>{}, env.app().getNodeFamily());
history.push_back(prev);
for (auto i = 0; i < (maxAncestors + 10); ++i)
{

View File

@@ -45,11 +45,7 @@ struct Regression_test : public beast::unit_test::suite
// be reproduced against an open ledger. Make a local
// closed ledger and work with it directly.
auto closed = std::make_shared<Ledger>(
create_genesis,
Rules{env.app().config().features},
env.app().config().FEES.toFees(),
std::vector<uint256>{},
env.app().getNodeFamily());
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
auto expectedDrops = INITIAL_XRP;
BEAST_EXPECT(closed->header().drops == expectedDrops);

View File

@@ -50,7 +50,7 @@ class io_latency_probe_test : public beast::unit_test::suite, public beast::test
bool done = false;
boost::system::error_code wait_err;
while (--num_samples > 0u)
while (--num_samples)
{
auto const start{MeasureClock::now()};
done = false;

View File

@@ -1,5 +1,6 @@
#include <xrpld/consensus/LedgerTiming.h>
#include <xrpl/beast/unit_test.h>
#include <xrpl/ledger/LedgerTiming.h>
namespace xrpl {
namespace test {

View File

@@ -1,6 +1,7 @@
#include <test/jtx.h>
#include <xrpld/app/consensus/RCLValidations.h>
#include <xrpld/app/ledger/Ledger.h>
#include <xrpld/app/misc/NegativeUNLVote.h>
#include <xrpld/app/misc/ValidatorList.h>
@@ -210,11 +211,7 @@ class NegativeUNL_test : public beast::unit_test::suite
std::vector<PublicKey> publicKeys = createPublicKeys(3);
// genesis ledger
auto l = std::make_shared<Ledger>(
create_genesis,
Rules{env.app().config().features},
env.app().config().FEES.toFees(),
std::vector<uint256>{},
env.app().getNodeFamily());
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
// Record the public keys and ledger sequences of expected negative UNL
// validators when we build the ledger history
@@ -546,8 +543,7 @@ struct NetworkHistory
static uint256 fake_amendment; // So we have different genesis ledgers
auto l = std::make_shared<Ledger>(
create_genesis,
Rules{env.app().config().features},
env.app().config().FEES.toFees(),
env.app().config(),
std::vector<uint256>{fake_amendment++},
env.app().getNodeFamily());
history.push_back(l);
@@ -1674,11 +1670,7 @@ class NegativeUNLVoteFilterValidations_test : public beast::unit_test::suite
testcase("Filter Validations");
jtx::Env env(*this);
auto l = std::make_shared<Ledger>(
create_genesis,
Rules{env.app().config().features},
env.app().config().FEES.toFees(),
std::vector<uint256>{},
env.app().getNodeFamily());
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
auto createSTVal = [&](std::pair<PublicKey, SecretKey> const& keys) {
return std::make_shared<STValidation>(

View File

@@ -2,12 +2,13 @@
#include <test/csf/Tx.h>
#include <xrpld/consensus/LedgerTiming.h>
#include <xrpl/basics/UnorderedContainers.h>
#include <xrpl/basics/chrono.h>
#include <xrpl/basics/comparators.h>
#include <xrpl/basics/tagged_integer.h>
#include <xrpl/json/json_value.h>
#include <xrpl/ledger/LedgerTiming.h>
#include <boost/bimap/bimap.hpp>

View File

@@ -11,17 +11,17 @@
#include <test/jtx/vault.h>
#include <test/unit_test/SuiteJournal.h>
#include <xrpld/app/ledger/Ledger.h>
#include <xrpld/app/ledger/OpenLedger.h>
#include <xrpld/app/main/Application.h>
#include <xrpld/app/paths/Pathfinder.h>
#include <xrpld/core/Config.h>
#include <xrpld/rpc/detail/Pathfinder.h>
#include <xrpl/basics/Log.h>
#include <xrpl/basics/chrono.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/json/json_value.h>
#include <xrpl/json/to_string.h>
#include <xrpl/ledger/Ledger.h>
#include <xrpl/protocol/ApiVersion.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>

View File

@@ -1,6 +1,6 @@
#include <test/jtx/paths.h>
#include <xrpld/rpc/detail/Pathfinder.h>
#include <xrpld/app/paths/Pathfinder.h>
#include <xrpl/protocol/jss.h>

View File

@@ -2,8 +2,9 @@
#include <test/jtx/Account.h>
#include <xrpld/app/ledger/Ledger.h>
#include <xrpl/json/json_value.h>
#include <xrpl/ledger/Ledger.h>
#include <xrpl/protocol/STObject.h>
#include <stdexcept>

View File

@@ -1,5 +1,6 @@
#include <xrpld/app/ledger/PendingSaves.h>
#include <xrpl/beast/unit_test.h>
#include <xrpl/ledger/PendingSaves.h>
namespace xrpl {
namespace test {

View File

@@ -1,7 +1,8 @@
#include <test/jtx/Env.h>
#include <xrpld/app/ledger/Ledger.h>
#include <xrpl/beast/unit_test.h>
#include <xrpl/ledger/Ledger.h>
#include <xrpl/ledger/View.h>
namespace xrpl {
@@ -17,11 +18,7 @@ class SkipList_test : public beast::unit_test::suite
{
Config config;
auto prev = std::make_shared<Ledger>(
create_genesis,
Rules{config.features},
config.FEES.toFees(),
std::vector<uint256>{},
env.app().getNodeFamily());
create_genesis, config, std::vector<uint256>{}, env.app().getNodeFamily());
history.push_back(prev);
for (auto i = 0; i < 1023; ++i)
{

View File

@@ -1,9 +1,9 @@
#include <test/jtx.h>
#include <xrpld/app/ledger/Ledger.h>
#include <xrpld/core/ConfigSections.h>
#include <xrpl/ledger/ApplyViewImpl.h>
#include <xrpl/ledger/Ledger.h>
#include <xrpl/ledger/OpenView.h>
#include <xrpl/ledger/PaymentSandbox.h>
#include <xrpl/ledger/Sandbox.h>
@@ -116,11 +116,7 @@ class View_test : public beast::unit_test::suite
Env env(*this);
Config config;
std::shared_ptr<Ledger const> const genesis = std::make_shared<Ledger>(
create_genesis,
Rules{config.features},
config.FEES.toFees(),
std::vector<uint256>{},
env.app().getNodeFamily());
create_genesis, config, std::vector<uint256>{}, env.app().getNodeFamily());
auto const ledger = std::make_shared<Ledger>(*genesis, env.app().timeKeeper().closeTime());
wipe(*ledger);
ReadView& v = *ledger;
@@ -383,11 +379,7 @@ class View_test : public beast::unit_test::suite
Env env(*this);
Config config;
std::shared_ptr<Ledger const> const genesis = std::make_shared<Ledger>(
create_genesis,
Rules{config.features},
config.FEES.toFees(),
std::vector<uint256>{},
env.app().getNodeFamily());
create_genesis, config, std::vector<uint256>{}, env.app().getNodeFamily());
auto const ledger = std::make_shared<Ledger>(*genesis, env.app().timeKeeper().closeTime());
auto setup = [&ledger](std::vector<int> const& vec) {
@@ -591,11 +583,7 @@ class View_test : public beast::unit_test::suite
Env env(*this);
Config config;
std::shared_ptr<Ledger const> const genesis = std::make_shared<Ledger>(
create_genesis,
Rules{config.features},
config.FEES.toFees(),
std::vector<uint256>{},
env.app().getNodeFamily());
create_genesis, config, std::vector<uint256>{}, env.app().getNodeFamily());
auto const ledger = std::make_shared<Ledger>(*genesis, env.app().timeKeeper().closeTime());
auto setup123 = [&ledger, this]() {
// erase middle element
@@ -941,11 +929,7 @@ class View_test : public beast::unit_test::suite
Env env(*this);
Config config;
std::shared_ptr<Ledger const> const genesis = std::make_shared<Ledger>(
create_genesis,
Rules{config.features},
config.FEES.toFees(),
std::vector<uint256>{},
env.app().getNodeFamily());
create_genesis, config, std::vector<uint256>{}, env.app().getNodeFamily());
auto const ledger =
std::make_shared<Ledger>(*genesis, env.app().timeKeeper().closeTime());
wipe(*ledger);

View File

@@ -4,6 +4,7 @@
#include <test/jtx/amount.h>
#include <test/jtx/pay.h>
#include <xrpld/app/ledger/Ledger.h>
#include <xrpld/app/ledger/LedgerMaster.h>
#include <xrpld/overlay/Compression.h>
#include <xrpld/overlay/Message.h>
@@ -14,7 +15,6 @@
#include <xrpl/basics/random.h>
#include <xrpl/beast/unit_test.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/ledger/Ledger.h>
#include <xrpl/protocol/HashPrefix.h>
#include <xrpl/protocol/PublicKey.h>
#include <xrpl/protocol/SecretKey.h>

View File

@@ -3,6 +3,7 @@
#include <xrpld/app/ledger/BuildLedger.h>
#include <xrpld/app/ledger/InboundLedgers.h>
#include <xrpld/app/ledger/InboundTransactions.h>
#include <xrpld/app/ledger/Ledger.h>
#include <xrpld/app/ledger/LedgerMaster.h>
#include <xrpld/app/ledger/LocalTxs.h>
#include <xrpld/app/ledger/OpenLedger.h>
@@ -10,6 +11,7 @@
#include <xrpld/app/misc/TxQ.h>
#include <xrpld/app/misc/ValidatorKeys.h>
#include <xrpld/app/misc/ValidatorList.h>
#include <xrpld/consensus/LedgerTiming.h>
#include <xrpld/overlay/Overlay.h>
#include <xrpld/overlay/predicates.h>
@@ -18,8 +20,6 @@
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/core/HashRouter.h>
#include <xrpl/ledger/AmendmentTable.h>
#include <xrpl/ledger/Ledger.h>
#include <xrpl/ledger/LedgerTiming.h>
#include <xrpl/protocol/BuildInfo.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/digest.h>

View File

@@ -1,8 +1,8 @@
#pragma once
#include <xrpld/app/ledger/Ledger.h>
#include <xrpld/app/ledger/LedgerToJson.h>
#include <xrpl/ledger/Ledger.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/protocol/RippleLedgerHash.h>

View File

@@ -1,8 +1,8 @@
#pragma once
#include <xrpld/app/ledger/Ledger.h>
#include <xrpld/consensus/Validations.h>
#include <xrpl/ledger/Ledger.h>
#include <xrpl/protocol/Protocol.h>
#include <xrpl/protocol/RippleLedgerHash.h>
#include <xrpl/protocol/STValidation.h>

View File

@@ -1,11 +1,11 @@
#pragma once
#include <xrpld/app/ledger/Ledger.h>
#include <xrpld/app/ledger/detail/TimeoutCounter.h>
#include <xrpld/app/main/Application.h>
#include <xrpld/overlay/PeerSet.h>
#include <xrpl/basics/CountedObject.h>
#include <xrpl/ledger/Ledger.h>
#include <mutex>
#include <set>

View File

@@ -1,9 +1,19 @@
#include <xrpld/app/ledger/InboundLedgers.h>
#include <xrpld/app/ledger/Ledger.h>
#include <xrpld/app/ledger/LedgerToJson.h>
#include <xrpld/app/ledger/PendingSaves.h>
#include <xrpld/app/main/Application.h>
#include <xrpld/consensus/LedgerTiming.h>
#include <xrpld/core/Config.h>
#include <xrpl/basics/Log.h>
#include <xrpl/basics/contract.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/core/HashRouter.h>
#include <xrpl/core/JobQueue.h>
#include <xrpl/json/to_string.h>
#include <xrpl/ledger/Ledger.h>
#include <xrpl/ledger/LedgerTiming.h>
#include <xrpl/nodestore/Database.h>
#include <xrpl/nodestore/detail/DatabaseNodeImp.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/HashPrefix.h>
#include <xrpl/protocol/Indexes.h>
@@ -11,6 +21,7 @@
#include <xrpl/protocol/SecretKey.h>
#include <xrpl/protocol/digest.h>
#include <xrpl/protocol/jss.h>
#include <xrpl/rdb/RelationalDatabase.h>
#include <utility>
#include <vector>
@@ -19,6 +30,23 @@ namespace xrpl {
create_genesis_t const create_genesis{};
uint256
calculateLedgerHash(LedgerHeader const& info)
{
// VFALCO This has to match addRaw in View.h.
return sha512Half(
HashPrefix::ledgerMaster,
std::uint32_t(info.seq),
std::uint64_t(info.drops.drops()),
info.parentHash,
info.txHash,
info.accountHash,
std::uint32_t(info.parentCloseTime.time_since_epoch().count()),
std::uint32_t(info.closeTime.time_since_epoch().count()),
std::uint8_t(info.closeTimeResolution.count()),
std::uint8_t(info.closeFlags));
}
//------------------------------------------------------------------------------
class Ledger::sles_iter_impl : public sles_type::iter_base
@@ -110,8 +138,8 @@ public:
{
auto const& item = *iter_;
if (metadata_)
return Ledger::deserializeTxPlusMeta(item);
return {Ledger::deserializeTx(item), nullptr};
return deserializeTxPlusMeta(item);
return {deserializeTx(item), nullptr};
}
};
@@ -119,15 +147,13 @@ public:
Ledger::Ledger(
create_genesis_t,
Rules const& rules,
Fees const& fees,
Config const& config,
std::vector<uint256> const& amendments,
Family& family)
: mImmutable(false)
, txMap_(SHAMapType::TRANSACTION, family)
, stateMap_(SHAMapType::STATE, family)
, fees_(fees)
, rules_(rules)
, rules_{config.features}
, j_(beast::Journal(beast::Journal::getNullSink()))
{
header_.seq = 1;
@@ -156,19 +182,19 @@ Ledger::Ledger(
// Whether featureXRPFees is supported will depend on startup options.
if (std::find(amendments.begin(), amendments.end(), featureXRPFees) != amendments.end())
{
sle->at(sfBaseFeeDrops) = fees.base;
sle->at(sfReserveBaseDrops) = fees.reserve;
sle->at(sfReserveIncrementDrops) = fees.increment;
sle->at(sfBaseFeeDrops) = config.FEES.reference_fee;
sle->at(sfReserveBaseDrops) = config.FEES.account_reserve;
sle->at(sfReserveIncrementDrops) = config.FEES.owner_reserve;
}
else
{
if (auto const f = fees.base.dropsAs<std::uint64_t>())
if (auto const f = config.FEES.reference_fee.dropsAs<std::uint64_t>())
sle->at(sfBaseFee) = *f;
if (auto const f = fees.reserve.dropsAs<std::uint32_t>())
if (auto const f = config.FEES.account_reserve.dropsAs<std::uint32_t>())
sle->at(sfReserveBase) = *f;
if (auto const f = fees.increment.dropsAs<std::uint32_t>())
if (auto const f = config.FEES.owner_reserve.dropsAs<std::uint32_t>())
sle->at(sfReserveIncrement) = *f;
sle->at(sfReferenceFeeUnits) = FEE_UNITS_DEPRECATED;
sle->at(sfReferenceFeeUnits) = Config::FEE_UNITS_DEPRECATED;
}
rawInsert(sle);
}
@@ -181,15 +207,13 @@ Ledger::Ledger(
LedgerHeader const& info,
bool& loaded,
bool acquire,
Rules const& rules,
Fees const& fees,
Config const& config,
Family& family,
beast::Journal j)
: mImmutable(true)
, txMap_(SHAMapType::TRANSACTION, info.txHash, family)
, stateMap_(SHAMapType::STATE, info.accountHash, family)
, fees_(fees)
, rules_(rules)
, rules_(config.features)
, header_(info)
, j_(j)
{
@@ -211,6 +235,7 @@ Ledger::Ledger(
txMap_.setImmutable();
stateMap_.setImmutable();
defaultFees(config);
if (!setup())
loaded = false;
@@ -250,11 +275,11 @@ Ledger::Ledger(Ledger const& prevLedger, NetClock::time_point closeTime)
}
}
Ledger::Ledger(LedgerHeader const& info, Rules const& rules, Family& family)
Ledger::Ledger(LedgerHeader const& info, Config const& config, Family& family)
: mImmutable(true)
, txMap_(SHAMapType::TRANSACTION, info.txHash, family)
, stateMap_(SHAMapType::STATE, info.accountHash, family)
, rules_(rules)
, rules_{config.features}
, header_(info)
, j_(beast::Journal(beast::Journal::getNullSink()))
{
@@ -264,19 +289,18 @@ Ledger::Ledger(LedgerHeader const& info, Rules const& rules, Family& family)
Ledger::Ledger(
std::uint32_t ledgerSeq,
NetClock::time_point closeTime,
Rules const& rules,
Fees const& fees,
Config const& config,
Family& family)
: mImmutable(false)
, txMap_(SHAMapType::TRANSACTION, family)
, stateMap_(SHAMapType::STATE, family)
, fees_(fees)
, rules_(rules)
, rules_{config.features}
, j_(beast::Journal(beast::Journal::getNullSink()))
{
header_.seq = ledgerSeq;
header_.closeTime = closeTime;
header_.closeTimeResolution = ledgerDefaultTimeResolution;
defaultFees(config);
setup();
}
@@ -326,14 +350,14 @@ Ledger::addSLE(SLE const& sle)
//------------------------------------------------------------------------------
std::shared_ptr<STTx const>
Ledger::deserializeTx(SHAMapItem const& item)
deserializeTx(SHAMapItem const& item)
{
SerialIter sit(item.slice());
return std::make_shared<STTx const>(sit);
}
std::pair<std::shared_ptr<STTx const>, std::shared_ptr<STObject const>>
Ledger::deserializeTxPlusMeta(SHAMapItem const& item)
deserializeTxPlusMeta(SHAMapItem const& item)
{
std::pair<std::shared_ptr<STTx const>, std::shared_ptr<STObject const>> result;
SerialIter sit(item.slice());
@@ -612,6 +636,20 @@ Ledger::setup()
return ret;
}
void
Ledger::defaultFees(Config const& config)
{
XRPL_ASSERT(
fees_.base == 0 && fees_.reserve == 0 && fees_.increment == 0,
"xrpl::Ledger::defaultFees : zero fees");
if (fees_.base == 0)
fees_.base = config.FEES.reference_fee;
if (fees_.reserve == 0)
fees_.reserve = config.FEES.account_reserve;
if (fees_.increment == 0)
fees_.increment = config.FEES.owner_reserve;
}
std::shared_ptr<SLE>
Ledger::peek(Keylet const& k) const
{
@@ -778,17 +816,27 @@ Ledger::walkLedger(beast::Journal j, bool parallel) const
}
bool
Ledger::isSensible() const
Ledger::assertSensible(beast::Journal ledgerJ) const
{
if (header_.hash.isZero())
return false;
if (header_.accountHash.isZero())
return false;
if (header_.accountHash != stateMap_.getHash().as_uint256())
return false;
if (header_.txHash != txMap_.getHash().as_uint256())
return false;
return true;
if (header_.hash.isNonZero() && header_.accountHash.isNonZero() &&
(header_.accountHash == stateMap_.getHash().as_uint256()) &&
(header_.txHash == txMap_.getHash().as_uint256()))
{
return true;
}
// LCOV_EXCL_START
Json::Value j = getJson({*this, {}});
j[jss::accountTreeHash] = to_string(header_.accountHash);
j[jss::transTreeHash] = to_string(header_.txHash);
JLOG(ledgerJ.fatal()) << "ledger is not sensible" << j;
UNREACHABLE("xrpl::Ledger::assertSensible : ledger is not sensible");
return false;
// LCOV_EXCL_STOP
}
// update the skip list with the information from our previous ledger
@@ -877,6 +925,76 @@ Ledger::isVotingLedger() const
return ::xrpl::isVotingLedger(header_.seq + 1);
}
static bool
saveValidatedLedger(Application& app, std::shared_ptr<Ledger const> const& ledger, bool current)
{
auto j = app.journal("Ledger");
auto seq = ledger->header().seq;
if (!app.pendingSaves().startWork(seq))
{
// The save was completed synchronously
JLOG(j.debug()) << "Save aborted";
return true;
}
auto& db = app.getRelationalDatabase();
auto const res = db.saveValidatedLedger(ledger, current);
// Clients can now trust the database for
// information about this ledger sequence.
app.pendingSaves().finishWork(seq);
return res;
}
/** Save, or arrange to save, a fully-validated ledger
Returns false on error
*/
bool
pendSaveValidated(
Application& app,
std::shared_ptr<Ledger const> const& ledger,
bool isSynchronous,
bool isCurrent)
{
if (!app.getHashRouter().setFlags(ledger->header().hash, HashRouterFlags::SAVED))
{
// We have tried to save this ledger recently
auto stream = app.journal("Ledger").debug();
JLOG(stream) << "Double pend save for " << ledger->header().seq;
if (!isSynchronous || !app.pendingSaves().pending(ledger->header().seq))
{
// Either we don't need it to be finished
// or it is finished
return true;
}
}
XRPL_ASSERT(ledger->isImmutable(), "xrpl::pendSaveValidated : immutable ledger");
if (!app.pendingSaves().shouldWork(ledger->header().seq, isSynchronous))
{
auto stream = app.journal("Ledger").debug();
JLOG(stream) << "Pend save with seq in pending saves " << ledger->header().seq;
return true;
}
// See if we can use the JobQueue.
if (!isSynchronous &&
app.getJobQueue().addJob(
isCurrent ? jtPUBLEDGER : jtPUBOLDLEDGER,
std::to_string(ledger->seq()),
[&app, ledger, isCurrent]() { saveValidatedLedger(app, ledger, isCurrent); }))
{
return true;
}
// The JobQueue won't do the Job. Do the save synchronously.
return saveValidatedLedger(app, ledger, isCurrent);
}
void
Ledger::unshare() const
{
@@ -890,5 +1008,84 @@ Ledger::invariants() const
stateMap_.invariants();
txMap_.invariants();
}
//------------------------------------------------------------------------------
/*
* Make ledger using info loaded from database.
*
* @param LedgerHeader: Ledger information.
* @param app: Link to the Application.
* @param acquire: Acquire the ledger if not found locally.
* @return Shared pointer to the ledger.
*/
std::shared_ptr<Ledger>
loadLedgerHelper(LedgerHeader const& info, Application& app, bool acquire)
{
bool loaded = false;
auto ledger = std::make_shared<Ledger>(
info, loaded, acquire, app.config(), app.getNodeFamily(), app.journal("Ledger"));
if (!loaded)
ledger.reset();
return ledger;
}
static void
finishLoadByIndexOrHash(
std::shared_ptr<Ledger> const& ledger,
Config const& config,
beast::Journal j)
{
if (!ledger)
return;
XRPL_ASSERT(
ledger->header().seq < XRP_LEDGER_EARLIEST_FEES || ledger->read(keylet::fees()),
"xrpl::finishLoadByIndexOrHash : valid ledger fees");
ledger->setImmutable();
JLOG(j.trace()) << "Loaded ledger: " << to_string(ledger->header().hash);
ledger->setFull();
}
std::tuple<std::shared_ptr<Ledger>, std::uint32_t, uint256>
getLatestLedger(Application& app)
{
std::optional<LedgerHeader> const info = app.getRelationalDatabase().getNewestLedgerInfo();
if (!info)
return {std::shared_ptr<Ledger>(), {}, {}};
return {loadLedgerHelper(*info, app, true), info->seq, info->hash};
}
std::shared_ptr<Ledger>
loadByIndex(std::uint32_t ledgerIndex, Application& app, bool acquire)
{
if (std::optional<LedgerHeader> info =
app.getRelationalDatabase().getLedgerInfoByIndex(ledgerIndex))
{
std::shared_ptr<Ledger> ledger = loadLedgerHelper(*info, app, acquire);
finishLoadByIndexOrHash(ledger, app.config(), app.journal("Ledger"));
return ledger;
}
return {};
}
std::shared_ptr<Ledger>
loadByHash(uint256 const& ledgerHash, Application& app, bool acquire)
{
if (std::optional<LedgerHeader> info =
app.getRelationalDatabase().getLedgerInfoByHash(ledgerHash))
{
std::shared_ptr<Ledger> ledger = loadLedgerHelper(*info, app, acquire);
finishLoadByIndexOrHash(ledger, app.config(), app.journal("Ledger"));
XRPL_ASSERT(
!ledger || ledger->header().hash == ledgerHash,
"xrpl::loadByHash : ledger hash match if loaded");
return ledger;
}
return {};
}
} // namespace xrpl

View File

@@ -1,12 +1,13 @@
#pragma once
#include <xrpld/core/Config.h>
#include <xrpld/core/TimeKeeper.h>
#include <xrpl/basics/CountedObject.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/ledger/CachedView.h>
#include <xrpl/ledger/View.h>
#include <xrpl/protocol/Fees.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/Rules.h>
#include <xrpl/protocol/STLedgerEntry.h>
#include <xrpl/protocol/Serializer.h>
#include <xrpl/protocol/TxMeta.h>
@@ -14,7 +15,7 @@
namespace xrpl {
class ServiceRegistry;
class Application;
class Job;
class TransactionMaster;
@@ -82,26 +83,21 @@ public:
*/
Ledger(
create_genesis_t,
Rules const& rules,
Fees const& fees,
Config const& config,
std::vector<uint256> const& amendments,
Family& family);
Ledger(LedgerHeader const& info, Rules const& rules, Family& family);
Ledger(LedgerHeader const& info, Config const& config, Family& family);
/** Used for ledgers loaded from JSON files
@param acquire If true, acquires the ledger if not found locally
@note The fees parameter provides default values, but setup() may
override them from the ledger state if fee-related SLEs exist.
*/
Ledger(
LedgerHeader const& info,
bool& loaded,
bool acquire,
Rules const& rules,
Fees const& fees,
Config const& config,
Family& family,
beast::Journal j);
@@ -117,8 +113,7 @@ public:
Ledger(
std::uint32_t ledgerSeq,
NetClock::time_point closeTime,
Rules const& rules,
Fees const& fees,
Config const& config,
Family& family);
~Ledger() = default;
@@ -327,7 +322,7 @@ public:
walkLedger(beast::Journal j, bool parallel = false) const;
bool
isSensible() const;
assertSensible(beast::Journal ledgerJ) const;
void
invariants() const;
@@ -384,26 +379,8 @@ private:
bool
setup();
/** @brief Deserialize a SHAMapItem containing a single STTx.
*
* @param item The SHAMapItem to deserialize.
* @return A shared pointer to the deserialized transaction.
* @throw May throw on deserialization error.
*/
static std::shared_ptr<STTx const>
deserializeTx(SHAMapItem const& item);
/** @brief Deserialize a SHAMapItem containing STTx + STObject metadata.
*
* The SHAMapItem must contain two variable length serialization objects.
*
* @param item The SHAMapItem to deserialize.
* @return A pair containing shared pointers to the deserialized transaction
* and metadata.
* @throw May throw on deserialization error.
*/
static std::pair<std::shared_ptr<STTx const>, std::shared_ptr<STObject const>>
deserializeTxPlusMeta(SHAMapItem const& item);
void
defaultFees(Config const& config);
bool mImmutable;
@@ -425,4 +402,54 @@ private:
/** A ledger wrapped in a CachedView. */
using CachedLedger = CachedView<Ledger>;
//------------------------------------------------------------------------------
//
// API
//
//------------------------------------------------------------------------------
extern bool
pendSaveValidated(
Application& app,
std::shared_ptr<Ledger const> const& ledger,
bool isSynchronous,
bool isCurrent);
std::shared_ptr<Ledger>
loadLedgerHelper(LedgerHeader const& sinfo, Application& app, bool acquire);
std::shared_ptr<Ledger>
loadByIndex(std::uint32_t ledgerIndex, Application& app, bool acquire = true);
std::shared_ptr<Ledger>
loadByHash(uint256 const& ledgerHash, Application& app, bool acquire = true);
// Fetch the ledger with the highest sequence contained in the database
extern std::tuple<std::shared_ptr<Ledger>, std::uint32_t, uint256>
getLatestLedger(Application& app);
/** Deserialize a SHAMapItem containing a single STTx
Throw:
May throw on deserializaton error
*/
std::shared_ptr<STTx const>
deserializeTx(SHAMapItem const& item);
/** Deserialize a SHAMapItem containing STTx + STObject metadata
The SHAMap must contain two variable length
serialization objects.
Throw:
May throw on deserializaton error
*/
std::pair<std::shared_ptr<STTx const>, std::shared_ptr<STObject const>>
deserializeTxPlusMeta(SHAMapItem const& item);
uint256
calculateLedgerHash(LedgerHeader const& info);
} // namespace xrpl

View File

@@ -1,7 +1,5 @@
#include <xrpld/app/ledger/LedgerHistory.h>
#include <xrpld/app/ledger/LedgerPersistence.h>
#include <xrpld/app/ledger/LedgerToJson.h>
#include <xrpld/app/main/Application.h>
#include <xrpl/basics/Log.h>
#include <xrpl/basics/chrono.h>
@@ -75,9 +73,7 @@ LedgerHistory::getLedgerBySeq(LedgerIndex index)
}
}
Rules const rules{app_.config().features};
Fees const fees = app_.config().FEES.toFees();
std::shared_ptr<Ledger const> ret = loadByIndex(index, rules, fees, app_);
std::shared_ptr<Ledger const> ret = loadByIndex(index, app_);
if (!ret)
return ret;
@@ -115,9 +111,7 @@ LedgerHistory::getLedgerByHash(LedgerHash const& hash)
return ret;
}
Rules const rules{app_.config().features};
Fees const fees = app_.config().FEES.toFees();
ret = loadByHash(hash, rules, fees, app_);
ret = loadByHash(hash, app_);
if (!ret)
return ret;

View File

@@ -1,9 +1,9 @@
#pragma once
#include <xrpld/app/ledger/Ledger.h>
#include <xrpld/app/main/Application.h>
#include <xrpl/beast/insight/Collector.h>
#include <xrpl/ledger/Ledger.h>
#include <xrpl/protocol/RippleLedgerHash.h>
#include <optional>

View File

@@ -2,18 +2,17 @@
#include <xrpld/app/ledger/AbstractFetchPackContainer.h>
#include <xrpld/app/ledger/InboundLedgers.h>
#include <xrpld/app/ledger/Ledger.h>
#include <xrpld/app/ledger/LedgerHistory.h>
#include <xrpld/app/ledger/LedgerHolder.h>
#include <xrpld/app/ledger/LedgerReplay.h>
#include <xrpld/app/main/Application.h>
#include <xrpld/core/TimeKeeper.h>
#include <xrpld/app/misc/CanonicalTXSet.h>
#include <xrpl/basics/RangeSet.h>
#include <xrpl/basics/UptimeClock.h>
#include <xrpl/basics/chrono.h>
#include <xrpl/beast/insight/Collector.h>
#include <xrpl/ledger/CanonicalTXSet.h>
#include <xrpl/ledger/Ledger.h>
#include <xrpl/protocol/Protocol.h>
#include <xrpl/protocol/RippleLedgerHash.h>
#include <xrpl/protocol/messages.h>

View File

@@ -1,90 +0,0 @@
#pragma once
#include <xrpl/ledger/Ledger.h>
#include <memory>
#include <tuple>
namespace xrpl {
class ServiceRegistry;
struct Fees;
/** Save, or arrange to save, a fully-validated ledger.
@param registry The service registry providing access to required services.
@param ledger The fully-validated ledger to save.
@param isSynchronous If true, wait for the save to complete.
@param isCurrent If true, the ledger is the current validated ledger.
@return false on error.
*/
bool
pendSaveValidated(
ServiceRegistry& registry,
std::shared_ptr<Ledger const> const& ledger,
bool isSynchronous,
bool isCurrent);
/** Make ledger using info loaded from database.
@param info Ledger information.
@param rules Rules to use (may be overwritten by setup()).
@param fees Fees to use (may be overwritten by setup()).
@param registry Service registry for dependency injection.
@param acquire Acquire the ledger if not found locally.
@return Shared pointer to the ledger.
*/
std::shared_ptr<Ledger>
loadLedgerHelper(
LedgerHeader const& info,
Rules const& rules,
Fees const& fees,
ServiceRegistry& registry,
bool acquire);
/** Load a ledger by its sequence number.
@param ledgerIndex The sequence number of the ledger to load.
@param rules Rules to use (may be overwritten by setup()).
@param fees Fees to use (may be overwritten by setup()).
@param registry Service registry for dependency injection.
@param acquire Acquire the ledger if not found locally.
@return Shared pointer to the ledger, or nullptr if not found.
*/
std::shared_ptr<Ledger>
loadByIndex(
std::uint32_t ledgerIndex,
Rules const& rules,
Fees const& fees,
ServiceRegistry& registry,
bool acquire = true);
/** Load a ledger by its hash.
@param ledgerHash The hash of the ledger to load.
@param rules Rules to use (may be overwritten by setup()).
@param fees Fees to use (may be overwritten by setup()).
@param registry Service registry for dependency injection.
@param acquire Acquire the ledger if not found locally.
@return Shared pointer to the ledger, or nullptr if not found.
*/
std::shared_ptr<Ledger>
loadByHash(
uint256 const& ledgerHash,
Rules const& rules,
Fees const& fees,
ServiceRegistry& registry,
bool acquire = true);
/** Fetch the ledger with the highest sequence contained in the database.
@param rules Rules to use (may be overwritten by setup()).
@param fees Fees to use (may be overwritten by setup()).
@param registry Service registry for dependency injection.
@return Tuple of (ledger, sequence, hash), or empty if not found.
*/
std::tuple<std::shared_ptr<Ledger>, std::uint32_t, uint256>
getLatestLedger(Rules const& rules, Fees const& fees, ServiceRegistry& registry);
} // namespace xrpl

View File

@@ -4,7 +4,6 @@
#include <cstdint>
#include <map>
#include <memory>
namespace xrpl {

View File

@@ -1,11 +1,11 @@
#pragma once
#include <xrpld/app/ledger/Ledger.h>
#include <xrpld/app/ledger/LedgerMaster.h>
#include <xrpld/app/misc/TxQ.h>
#include <xrpld/rpc/Context.h>
#include <xrpl/basics/chrono.h>
#include <xrpl/ledger/Ledger.h>
#include <xrpl/protocol/serialize.h>
namespace xrpl {

View File

@@ -1,6 +1,7 @@
#pragma once
#include <xrpl/ledger/CanonicalTXSet.h>
#include <xrpld/app/misc/CanonicalTXSet.h>
#include <xrpl/ledger/ReadView.h>
#include <memory>

View File

@@ -1,5 +1,7 @@
#pragma once
#include <xrpld/app/ledger/Ledger.h>
#include <xrpld/app/misc/CanonicalTXSet.h>
#include <xrpld/core/Config.h>
#include <xrpl/basics/Log.h>
@@ -7,8 +9,6 @@
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/CachedSLEs.h>
#include <xrpl/ledger/CanonicalTXSet.h>
#include <xrpl/ledger/Ledger.h>
#include <xrpl/ledger/OpenView.h>
#include <mutex>

View File

@@ -1,10 +1,10 @@
#include <xrpld/app/ledger/BuildLedger.h>
#include <xrpld/app/ledger/Ledger.h>
#include <xrpld/app/ledger/LedgerReplay.h>
#include <xrpld/app/ledger/OpenLedger.h>
#include <xrpld/app/main/Application.h>
#include <xrpld/app/misc/CanonicalTXSet.h>
#include <xrpl/ledger/CanonicalTXSet.h>
#include <xrpl/ledger/Ledger.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/tx/apply.h>

View File

@@ -224,9 +224,8 @@ InboundLedger::tryDB(NodeStore::Database& srcDB)
{
auto makeLedger = [&, this](Blob const& data) {
JLOG(journal_.trace()) << "Ledger header found in fetch pack";
Rules const rules{app_.config().features};
mLedger = std::make_shared<Ledger>(
deserializePrefixedHeader(makeSlice(data)), rules, app_.getNodeFamily());
deserializePrefixedHeader(makeSlice(data)), app_.config(), app_.getNodeFamily());
if (mLedger->header().hash != hash_ || (mSeq != 0 && mSeq != mLedger->header().seq))
{
// We know for a fact the ledger can never be acquired
@@ -778,8 +777,7 @@ InboundLedger::takeHeader(std::string const& data)
return true;
auto* f = &app_.getNodeFamily();
Rules const rules{app_.config().features};
mLedger = std::make_shared<Ledger>(deserializeHeader(makeSlice(data)), rules, *f);
mLedger = std::make_shared<Ledger>(deserializeHeader(makeSlice(data)), app_.config(), *f);
if (mLedger->header().hash != hash_ || (mSeq != 0 && mSeq != mLedger->header().seq))
{
JLOG(journal_.warn()) << "Acquire hash mismatch: " << mLedger->header().hash

View File

@@ -1,8 +1,6 @@
#include <xrpld/app/ledger/InboundLedgers.h>
#include <xrpld/app/ledger/LedgerCleaner.h>
#include <xrpld/app/ledger/LedgerMaster.h>
#include <xrpld/app/ledger/LedgerPersistence.h>
#include <xrpld/app/main/Application.h>
#include <xrpl/beast/core/CurrentThreadName.h>
#include <xrpl/protocol/jss.h>
@@ -263,9 +261,7 @@ private:
return false;
}
Rules const rules{app_.config().features};
Fees const fees = app_.config().FEES.toFees();
auto const dbLedger = loadByIndex(ledgerIndex, rules, fees, app_);
auto dbLedger = loadByIndex(ledgerIndex, app_);
if (!dbLedger || (dbLedger->header().hash != ledgerHash) ||
(dbLedger->header().parentHash != nodeLedger->header().parentHash))
{

View File

@@ -124,8 +124,7 @@ LedgerDeltaAcquire::processData(
if (info.seq == ledgerSeq_)
{
// create a temporary ledger for building a LedgerReplay object later
Rules const rules{app_.config().features};
replayTemp_ = std::make_shared<Ledger>(info, rules, app_.getNodeFamily());
replayTemp_ = std::make_shared<Ledger>(info, app_.config(), app_.getNodeFamily());
if (replayTemp_)
{
complete_ = true;

View File

@@ -1,11 +1,11 @@
#pragma once
#include <xrpld/app/ledger/InboundLedger.h>
#include <xrpld/app/ledger/Ledger.h>
#include <xrpld/app/ledger/detail/TimeoutCounter.h>
#include <xrpl/basics/CountedObject.h>
#include <xrpl/basics/base_uint.h>
#include <xrpl/ledger/Ledger.h>
#include <map>

View File

@@ -1,17 +1,18 @@
#include <xrpld/app/consensus/RCLValidations.h>
#include <xrpld/app/ledger/Ledger.h>
#include <xrpld/app/ledger/LedgerMaster.h>
#include <xrpld/app/ledger/LedgerPersistence.h>
#include <xrpld/app/ledger/LedgerReplayer.h>
#include <xrpld/app/ledger/OpenLedger.h>
#include <xrpld/app/ledger/PendingSaves.h>
#include <xrpld/app/main/Application.h>
#include <xrpld/app/misc/SHAMapStore.h>
#include <xrpld/app/misc/Transaction.h>
#include <xrpld/app/misc/TxQ.h>
#include <xrpld/app/misc/ValidatorList.h>
#include <xrpld/app/paths/PathRequests.h>
#include <xrpld/core/TimeKeeper.h>
#include <xrpld/overlay/Overlay.h>
#include <xrpld/overlay/Peer.h>
#include <xrpld/rpc/detail/PathRequestManager.h>
#include <xrpl/basics/Log.h>
#include <xrpl/basics/MathUtilities.h>
@@ -21,9 +22,7 @@
#include <xrpl/basics/scope.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/AmendmentTable.h>
#include <xrpl/ledger/Ledger.h>
#include <xrpl/ledger/OrderBookDB.h>
#include <xrpl/ledger/PendingSaves.h>
#include <xrpl/protocol/BuildInfo.h>
#include <xrpl/protocol/HashPrefix.h>
#include <xrpl/protocol/digest.h>
@@ -1390,7 +1389,7 @@ LedgerMaster::updatePaths()
try
{
auto& pathRequests = app_.getPathRequestManager();
auto& pathRequests = app_.getPathRequests();
{
std::lock_guard ml(m_mutex);
if (!pathRequests.requestsPending())
@@ -1472,7 +1471,7 @@ LedgerMaster::newOrderBookDB()
bool
LedgerMaster::newPFWork(char const* name, std::unique_lock<std::recursive_mutex>&)
{
if (!app_.isStopping() && mPathFindThread < 2 && app_.getPathRequestManager().requestsPending())
if (!app_.isStopping() && mPathFindThread < 2 && app_.getPathRequests().requestsPending())
{
JLOG(m_journal.debug()) << "newPFWork: Creating job. path find threads: "
<< mPathFindThread;

View File

@@ -1,167 +0,0 @@
#include <xrpld/app/ledger/LedgerPersistence.h>
#include <xrpl/basics/Log.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/core/HashRouter.h>
#include <xrpl/core/JobQueue.h>
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/json/to_string.h>
#include <xrpl/ledger/PendingSaves.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/rdb/RelationalDatabase.h>
namespace xrpl {
static bool
saveValidatedLedger(
ServiceRegistry& registry,
std::shared_ptr<Ledger const> const& ledger,
bool current)
{
auto j = registry.journal("Ledger");
auto seq = ledger->header().seq;
if (!registry.pendingSaves().startWork(seq))
{
// The save was completed synchronously
JLOG(j.debug()) << "Save aborted";
return true;
}
auto& db = registry.getRelationalDatabase();
auto const res = db.saveValidatedLedger(ledger, current);
// Clients can now trust the database for
// information about this ledger sequence.
registry.pendingSaves().finishWork(seq);
return res;
}
bool
pendSaveValidated(
ServiceRegistry& registry,
std::shared_ptr<Ledger const> const& ledger,
bool isSynchronous,
bool isCurrent)
{
if (!registry.getHashRouter().setFlags(ledger->header().hash, HashRouterFlags::SAVED))
{
// We have tried to save this ledger recently
auto stream = registry.journal("Ledger").debug();
JLOG(stream) << "Double pend save for " << ledger->header().seq;
if (!isSynchronous || !registry.pendingSaves().pending(ledger->header().seq))
{
// Either we don't need it to be finished
// or it is finished
return true;
}
}
XRPL_ASSERT(ledger->isImmutable(), "xrpl::pendSaveValidated : immutable ledger");
if (!registry.pendingSaves().shouldWork(ledger->header().seq, isSynchronous))
{
auto stream = registry.journal("Ledger").debug();
JLOG(stream) << "Pend save with seq in pending saves " << ledger->header().seq;
return true;
}
// See if we can use the JobQueue.
if (!isSynchronous &&
registry.getJobQueue().addJob(
isCurrent ? jtPUBLEDGER : jtPUBOLDLEDGER,
std::to_string(ledger->seq()),
[&registry, ledger, isCurrent]() { saveValidatedLedger(registry, ledger, isCurrent); }))
{
return true;
}
// The JobQueue won't do the Job. Do the save synchronously.
return saveValidatedLedger(registry, ledger, isCurrent);
}
std::shared_ptr<Ledger>
loadLedgerHelper(
LedgerHeader const& info,
Rules const& rules,
Fees const& fees,
ServiceRegistry& registry,
bool acquire)
{
bool loaded = false;
auto ledger = std::make_shared<Ledger>(
info, loaded, acquire, rules, fees, registry.getNodeFamily(), registry.journal("Ledger"));
if (!loaded)
ledger.reset();
return ledger;
}
static void
finishLoadByIndexOrHash(std::shared_ptr<Ledger> const& ledger, beast::Journal j)
{
if (!ledger)
return;
XRPL_ASSERT(
ledger->header().seq < XRP_LEDGER_EARLIEST_FEES || ledger->read(keylet::fees()),
"xrpl::finishLoadByIndexOrHash : valid ledger fees");
ledger->setImmutable();
JLOG(j.trace()) << "Loaded ledger: " << to_string(ledger->header().hash);
ledger->setFull();
}
std::tuple<std::shared_ptr<Ledger>, std::uint32_t, uint256>
getLatestLedger(Rules const& rules, Fees const& fees, ServiceRegistry& registry)
{
std::optional<LedgerHeader> const info = registry.getRelationalDatabase().getNewestLedgerInfo();
if (!info)
return {std::shared_ptr<Ledger>(), {}, {}};
return {loadLedgerHelper(*info, rules, fees, registry, true), info->seq, info->hash};
}
std::shared_ptr<Ledger>
loadByIndex(
std::uint32_t ledgerIndex,
Rules const& rules,
Fees const& fees,
ServiceRegistry& registry,
bool acquire)
{
if (std::optional<LedgerHeader> info =
registry.getRelationalDatabase().getLedgerInfoByIndex(ledgerIndex))
{
std::shared_ptr<Ledger> ledger = loadLedgerHelper(*info, rules, fees, registry, acquire);
finishLoadByIndexOrHash(ledger, registry.journal("Ledger"));
return ledger;
}
return {};
}
std::shared_ptr<Ledger>
loadByHash(
uint256 const& ledgerHash,
Rules const& rules,
Fees const& fees,
ServiceRegistry& registry,
bool acquire)
{
if (std::optional<LedgerHeader> info =
registry.getRelationalDatabase().getLedgerInfoByHash(ledgerHash))
{
std::shared_ptr<Ledger> ledger = loadLedgerHelper(*info, rules, fees, registry, acquire);
finishLoadByIndexOrHash(ledger, registry.journal("Ledger"));
XRPL_ASSERT(
!ledger || ledger->header().hash == ledgerHash,
"xrpl::loadByHash : ledger hash match if loaded");
return ledger;
}
return {};
}
} // namespace xrpl

View File

@@ -1,7 +1,6 @@
#include <xrpld/app/ledger/Ledger.h>
#include <xrpld/app/ledger/LedgerReplay.h>
#include <xrpl/ledger/Ledger.h>
namespace xrpl {
LedgerReplay::LedgerReplay(

View File

@@ -1,6 +1,6 @@
#include <xrpld/app/ledger/Ledger.h>
#include <xrpld/app/ledger/LocalTxs.h>
#include <xrpl/ledger/Ledger.h>
#include <xrpl/protocol/Indexes.h>
/*

View File

@@ -1,7 +1,6 @@
#include <xrpld/app/ledger/OpenLedger.h>
#include <xrpld/app/main/Application.h>
#include <xrpld/app/misc/TxQ.h>
#include <xrpld/core/TimeKeeper.h>
#include <xrpld/overlay/Message.h>
#include <xrpld/overlay/Overlay.h>

View File

@@ -1,10 +1,10 @@
#pragma once
#include <xrpld/app/ledger/InboundLedger.h>
#include <xrpld/app/ledger/Ledger.h>
#include <xrpld/app/ledger/detail/TimeoutCounter.h>
#include <xrpld/app/main/Application.h>
#include <xrpl/ledger/Ledger.h>
#include <xrpl/shamap/SHAMap.h>
namespace xrpl {

View File

@@ -3,11 +3,11 @@
#include <xrpld/app/ledger/InboundTransactions.h>
#include <xrpld/app/ledger/LedgerCleaner.h>
#include <xrpld/app/ledger/LedgerMaster.h>
#include <xrpld/app/ledger/LedgerPersistence.h>
#include <xrpld/app/ledger/LedgerReplayer.h>
#include <xrpld/app/ledger/LedgerToJson.h>
#include <xrpld/app/ledger/OpenLedger.h>
#include <xrpld/app/ledger/OrderBookDBImpl.h>
#include <xrpld/app/ledger/PendingSaves.h>
#include <xrpld/app/ledger/TransactionMaster.h>
#include <xrpld/app/main/Application.h>
#include <xrpld/app/main/BasicApp.h>
@@ -21,13 +21,13 @@
#include <xrpld/app/misc/ValidatorSite.h>
#include <xrpld/app/misc/make_NetworkOPs.h>
#include <xrpld/app/misc/setup_HashRouter.h>
#include <xrpld/app/paths/PathRequests.h>
#include <xrpld/app/rdb/backend/SQLiteDatabase.h>
#include <xrpld/core/ConfigSections.h>
#include <xrpld/core/NetworkIDServiceImpl.h>
#include <xrpld/overlay/Cluster.h>
#include <xrpld/overlay/PeerSet.h>
#include <xrpld/overlay/make_Overlay.h>
#include <xrpld/rpc/detail/PathRequestManager.h>
#include <xrpld/shamap/NodeFamily.h>
#include <xrpl/basics/ByteUtilities.h>
@@ -42,7 +42,6 @@
#include <xrpl/crypto/csprng.h>
#include <xrpl/json/json_reader.h>
#include <xrpl/ledger/AmendmentTable.h>
#include <xrpl/ledger/PendingSaves.h>
#include <xrpl/nodestore/DummyScheduler.h>
#include <xrpl/protocol/ApiVersion.h>
#include <xrpl/protocol/BuildInfo.h>
@@ -171,7 +170,7 @@ public:
std::unique_ptr<NodeStore::Database> m_nodeStore;
NodeFamily nodeFamily_;
std::unique_ptr<OrderBookDB> m_orderBookDB;
std::unique_ptr<PathRequestManager> m_pathRequestManager;
std::unique_ptr<PathRequests> m_pathRequests;
std::unique_ptr<LedgerMaster> m_ledgerMaster;
std::unique_ptr<LedgerCleaner> ledgerCleaner_;
std::unique_ptr<InboundLedgers> m_inboundLedgers;
@@ -331,8 +330,8 @@ public:
, m_orderBookDB(make_OrderBookDB(*this, {config_->PATH_SEARCH_MAX, config_->standalone()}))
, m_pathRequestManager(
std::make_unique<PathRequestManager>(
, m_pathRequests(
std::make_unique<PathRequests>(
*this,
logs_->journal("PathRequest"),
m_collectorManager->collector()))
@@ -661,10 +660,10 @@ public:
return *m_orderBookDB;
}
PathRequestManager&
getPathRequestManager() override
PathRequests&
getPathRequests() override
{
return *m_pathRequestManager;
return *m_pathRequests;
}
CachedSLEs&
@@ -1640,12 +1639,8 @@ ApplicationImp::startGenesisLedger()
? m_amendmentTable->getDesired()
: std::vector<uint256>{};
std::shared_ptr<Ledger> const genesis = std::make_shared<Ledger>(
create_genesis,
Rules{config_->features},
config_->FEES.toFees(),
initialAmendments,
nodeFamily_);
std::shared_ptr<Ledger> const genesis =
std::make_shared<Ledger>(create_genesis, *config_, initialAmendments, nodeFamily_);
m_ledgerMaster->storeLedger(genesis);
auto const next = std::make_shared<Ledger>(*genesis, timeKeeper().closeTime());
@@ -1666,8 +1661,7 @@ ApplicationImp::getLastFullLedger()
try
{
auto const [ledger, seq, hash] =
getLatestLedger(Rules{config_->features}, config_->FEES.toFees(), *this);
auto const [ledger, seq, hash] = getLatestLedger(*this);
if (!ledger)
return ledger;
@@ -1778,8 +1772,7 @@ ApplicationImp::loadLedgerFromFile(std::string const& name)
return nullptr;
}
auto loadLedger = std::make_shared<Ledger>(
seq, closeTime, Rules{config_->features}, config_->FEES.toFees(), nodeFamily_);
auto loadLedger = std::make_shared<Ledger>(seq, closeTime, *config_, nodeFamily_);
loadLedger->setTotalDrops(totalDrops);
for (Json::UInt index = 0; index < ledger.get().size(); ++index)
@@ -1859,8 +1852,7 @@ ApplicationImp::loadOldLedger(
if (hash.parseHex(ledgerID))
{
loadLedger =
loadByHash(hash, Rules{config_->features}, config_->FEES.toFees(), *this);
loadLedger = loadByHash(hash, *this);
if (!loadLedger)
{
@@ -1887,10 +1879,7 @@ ApplicationImp::loadOldLedger(
std::uint32_t index = 0;
if (beast::lexicalCastChecked(index, ledgerID))
{
loadLedger =
loadByIndex(index, Rules{config_->features}, config_->FEES.toFees(), *this);
}
loadLedger = loadByIndex(index, *this);
}
if (!loadLedger)
@@ -1905,11 +1894,7 @@ ApplicationImp::loadOldLedger(
JLOG(m_journal.info()) << "Loading parent ledger";
loadLedger = loadByHash(
replayLedger->header().parentHash,
Rules{config_->features},
config_->FEES.toFees(),
*this);
loadLedger = loadByHash(replayLedger->header().parentHash, *this);
if (!loadLedger)
{
JLOG(m_journal.info()) << "Loading parent ledger from node store";
@@ -1978,13 +1963,10 @@ ApplicationImp::loadOldLedger(
// LCOV_EXCL_STOP
}
if (!loadLedger->isSensible())
if (!loadLedger->assertSensible(journal("Ledger")))
{
// LCOV_EXCL_START
Json::Value j = getJson({*loadLedger, {}});
j[jss::accountTreeHash] = to_string(loadLedger->header().accountHash);
j[jss::transTreeHash] = to_string(loadLedger->header().txHash);
JLOG(m_journal.fatal()) << "Ledger is not sensible: " << j;
JLOG(m_journal.fatal()) << "Ledger is not sensible.";
UNREACHABLE(
"xrpl::ApplicationImp::loadOldLedger : ledger is not "
"sensible");

View File

@@ -66,7 +66,7 @@ class NetworkOPs;
class OpenLedger;
class OrderBookDB;
class Overlay;
class PathRequestManager;
class PathRequests;
class PendingSaves;
class PublicKey;
class ServerHandler;

View File

@@ -1,4 +1,4 @@
#include <xrpl/ledger/CanonicalTXSet.h>
#include <xrpld/app/misc/CanonicalTXSet.h>
namespace xrpl {

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