mirror of
https://github.com/XRPLF/rippled.git
synced 2026-08-25 16:20:58 +00:00
Compare commits
1 Commits
ripple/was
...
peng/numbe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b523ee5843 |
24
.codecov.yml
24
.codecov.yml
@@ -1,32 +1,10 @@
|
||||
codecov:
|
||||
require_ci_to_pass: true
|
||||
# The C++ and Rust uploads land minutes apart; without this gate Codecov
|
||||
# publishes a near-zero total from whichever one arrives first.
|
||||
notify:
|
||||
after_n_builds: 2
|
||||
wait_for_ci: true
|
||||
|
||||
comment:
|
||||
behavior: default
|
||||
layout: reach,diff,flags,tree,reach
|
||||
show_carryforward_flags: true
|
||||
after_n_builds: 2
|
||||
|
||||
# C++ and Rust coverage upload from independent workflows under the `cpp` and
|
||||
# `rust` flags; carryforward keeps one language's total when only the other reran.
|
||||
flag_management:
|
||||
default_rules:
|
||||
carryforward: true
|
||||
individual_flags:
|
||||
- name: cpp
|
||||
carryforward: true
|
||||
paths:
|
||||
- include/
|
||||
- src/
|
||||
- name: rust
|
||||
carryforward: true
|
||||
paths:
|
||||
- crates/
|
||||
show_carryforward_flags: false
|
||||
|
||||
coverage:
|
||||
range: "70..85"
|
||||
|
||||
@@ -7,7 +7,6 @@ ignorePaths:
|
||||
- cmake/**
|
||||
- LICENSE.md
|
||||
- .clang-tidy
|
||||
- nix/check-tools/*.txt # generated, and full of Nix store hashes
|
||||
language: en
|
||||
allowCompoundWords: true # TODO (#6334)
|
||||
ignoreRandomStrings: true
|
||||
@@ -69,7 +68,6 @@ words:
|
||||
- Buildx
|
||||
- canonicality
|
||||
- canonicalised
|
||||
- cctools
|
||||
- changespq
|
||||
- checkme
|
||||
- choco
|
||||
@@ -111,7 +109,6 @@ words:
|
||||
- disablerepo
|
||||
- distro
|
||||
- doxyfile
|
||||
- dsymutil
|
||||
- dxrpl
|
||||
- elgamal
|
||||
- enabled
|
||||
@@ -170,7 +167,6 @@ words:
|
||||
- LOCALGOOD
|
||||
- logwstream
|
||||
- Lombrozo
|
||||
- lresolv
|
||||
- lseq
|
||||
- lsmf
|
||||
- ltype
|
||||
@@ -224,7 +220,6 @@ words:
|
||||
- Nyffenegger
|
||||
- onlatest
|
||||
- ostr
|
||||
- otool
|
||||
- oxalica
|
||||
- pargs
|
||||
- partitioner
|
||||
@@ -254,15 +249,11 @@ words:
|
||||
- Raphson
|
||||
- rcflags
|
||||
- replayer
|
||||
- repodata
|
||||
- repomd
|
||||
- rerandomize
|
||||
- rerandomization
|
||||
- rerandomized
|
||||
- rerandomizes
|
||||
- rerere
|
||||
- retargeted
|
||||
- retargets
|
||||
- retriable
|
||||
- RIPD
|
||||
- ripdtop
|
||||
@@ -298,7 +289,6 @@ words:
|
||||
- sles
|
||||
- soci
|
||||
- socidb
|
||||
- Sonatype
|
||||
- sponsee
|
||||
- sponsees
|
||||
- SRPMS
|
||||
@@ -318,7 +308,6 @@ words:
|
||||
- summands
|
||||
- superpeer
|
||||
- superpeers
|
||||
- Swatinem
|
||||
- takergets
|
||||
- takerpays
|
||||
- ters
|
||||
@@ -374,7 +363,6 @@ words:
|
||||
- wthread
|
||||
- xbridge
|
||||
- xchain
|
||||
- xcrun
|
||||
- ximinez
|
||||
- XMACRO
|
||||
- xored
|
||||
@@ -384,5 +372,4 @@ words:
|
||||
- xrplf
|
||||
- xxhash
|
||||
- xxhasher
|
||||
- zstdio
|
||||
- CGNAT
|
||||
|
||||
38
.github/actions/cargo-cache/action.yml
vendored
38
.github/actions/cargo-cache/action.yml
vendored
@@ -1,38 +0,0 @@
|
||||
name: Use cargo artifacts cache
|
||||
description: >
|
||||
Cache the cargo build artifacts with rust-cache. Never caches ~/.cargo/bin:
|
||||
when saving the cache, rust-cache deletes all binaries that were already
|
||||
present there, which on persistent self-hosted runners wipes the tools
|
||||
installed by prepare-runner. Harmless on ephemeral runners, but kept
|
||||
consistent everywhere.
|
||||
|
||||
inputs:
|
||||
workspaces:
|
||||
description: "Workspaces to cache, as 'workspace -> target' lines."
|
||||
required: false
|
||||
default: crates
|
||||
key:
|
||||
description: "Additional part of the cache key."
|
||||
required: false
|
||||
default: ""
|
||||
cache-directories:
|
||||
description: "Additional non-workspace directories to cache."
|
||||
required: false
|
||||
default: ""
|
||||
save-if:
|
||||
description: "Condition for saving the cache after the job."
|
||||
required: false
|
||||
default: "true"
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
|
||||
steps:
|
||||
- name: Use cargo artifacts cache
|
||||
uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
|
||||
with:
|
||||
cache-bin: "false"
|
||||
cache-directories: ${{ inputs.cache-directories }}
|
||||
key: ${{ inputs.key }}
|
||||
save-if: ${{ inputs.save-if }}
|
||||
workspaces: ${{ inputs.workspaces }}
|
||||
44
.github/actions/generate-version/action.yml
vendored
Normal file
44
.github/actions/generate-version/action.yml
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
name: Generate build version number
|
||||
description: "Generate build version number."
|
||||
|
||||
outputs:
|
||||
version:
|
||||
description: "The generated build version number."
|
||||
value: ${{ steps.version.outputs.version }}
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
# When a tag is pushed, the version is used as-is.
|
||||
- name: Generate version for tag event
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/') }}
|
||||
shell: bash
|
||||
env:
|
||||
VERSION: ${{ github.ref_name }}
|
||||
run: echo "VERSION=${VERSION}" >>"${GITHUB_ENV}"
|
||||
|
||||
# When a tag is not pushed, then the version (e.g. 1.2.3-b0) is extracted
|
||||
# from the BuildInfo.cpp file and the shortened commit hash appended to it.
|
||||
# We use a plus sign instead of a hyphen because Conan recipe versions do
|
||||
# not support two hyphens.
|
||||
- name: Generate version for non-tag event
|
||||
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
||||
shell: bash
|
||||
run: |
|
||||
echo 'Extracting version from BuildInfo.cpp.'
|
||||
VERSION="$(cat src/libxrpl/protocol/BuildInfo.cpp | grep "versionString =" | awk -F '"' '{print $2}')"
|
||||
if [[ -z "${VERSION}" ]]; then
|
||||
echo 'Unable to extract version from BuildInfo.cpp.'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo 'Appending shortened commit hash to version.'
|
||||
SHA='${{ github.sha }}'
|
||||
VERSION="${VERSION}+${SHA:0:7}"
|
||||
|
||||
echo "VERSION=${VERSION}" >>"${GITHUB_ENV}"
|
||||
|
||||
- name: Output version
|
||||
id: version
|
||||
shell: bash
|
||||
run: echo "version=${VERSION}" >>"${GITHUB_OUTPUT}"
|
||||
90
.github/actions/release-info/action.yml
vendored
90
.github/actions/release-info/action.yml
vendored
@@ -1,90 +0,0 @@
|
||||
name: Release info
|
||||
description: "Derive the version, release channel and package release number for this build."
|
||||
|
||||
outputs:
|
||||
version:
|
||||
description: "The build version number."
|
||||
value: ${{ steps.version.outputs.version }}
|
||||
channel:
|
||||
description: "The release channel this build belongs to."
|
||||
value: ${{ steps.channel.outputs.channel }}
|
||||
pkg_release:
|
||||
description: "The package release number: 1 for a tag, the run number otherwise."
|
||||
value: ${{ steps.pkg_release.outputs.pkg_release }}
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
# A tag names its own version. Anything else takes it from BuildInfo.cpp and
|
||||
# appends the commit hash as build metadata, joined with a plus sign because a
|
||||
# Conan version cannot contain two hyphens.
|
||||
- name: Determine version
|
||||
id: version
|
||||
shell: bash
|
||||
env:
|
||||
IS_TAG: ${{ startsWith(github.ref, 'refs/tags/') }}
|
||||
REF_NAME: ${{ github.ref_name }}
|
||||
SHA: ${{ github.sha }}
|
||||
run: |
|
||||
if [[ "${IS_TAG}" == "true" ]]; then
|
||||
version="${REF_NAME}"
|
||||
else
|
||||
version="$(awk -F'"' '/versionString =/ { print $2 }' src/libxrpl/protocol/BuildInfo.cpp)"
|
||||
if [[ -z "${version}" ]]; then
|
||||
echo "Unable to read versionString from BuildInfo.cpp." >&2
|
||||
exit 1
|
||||
fi
|
||||
version="${version}+${SHA:0:7}"
|
||||
fi
|
||||
|
||||
echo "version=${version}" | tee -a "${GITHUB_OUTPUT}"
|
||||
|
||||
# Only a tag says how mature a build is: a push is a develop build whatever
|
||||
# its version, and a non-public codebase keeps its packages to itself.
|
||||
- name: Determine release channel
|
||||
id: channel
|
||||
shell: bash
|
||||
env:
|
||||
IS_TAG: ${{ startsWith(github.ref, 'refs/tags/') }}
|
||||
REF_NAME: ${{ github.ref_name }}
|
||||
VISIBILITY: ${{ github.event.repository.visibility }}
|
||||
run: |
|
||||
pre_release=""
|
||||
if [[ "${REF_NAME}" == *-* ]]; then
|
||||
pre_release="${REF_NAME#*-}"
|
||||
fi
|
||||
|
||||
if [[ "${VISIBILITY}" != "public" ]]; then
|
||||
channel=private
|
||||
elif [[ "${IS_TAG}" != "true" ]]; then
|
||||
channel=develop
|
||||
elif [[ -z "${pre_release}" ]]; then
|
||||
channel=stable
|
||||
elif [[ "${pre_release}" =~ ^rc[0-9]+(\+.*)?$ ]]; then
|
||||
channel=unstable
|
||||
elif [[ "${pre_release}" =~ ^b(0|[1-9][0-9]*)(\+.*)?$ ]]; then
|
||||
channel=experimental
|
||||
else
|
||||
echo "Unsupported pre-release in tag '${REF_NAME}'. Use bN or rcN." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "channel=${channel}" | tee -a "${GITHUB_OUTPUT}"
|
||||
|
||||
# A tag is packaged once, so its release number is fixed at 1. Develop builds
|
||||
# repeat the same version, so the run number is what makes each push an
|
||||
# upgrade rather than a reinstall.
|
||||
- name: Determine package release
|
||||
id: pkg_release
|
||||
shell: bash
|
||||
env:
|
||||
IS_TAG: ${{ startsWith(github.ref, 'refs/tags/') }}
|
||||
RUN_NUMBER: ${{ github.run_number }}
|
||||
run: |
|
||||
if [[ "${IS_TAG}" == "true" ]]; then
|
||||
pkg_release=1
|
||||
else
|
||||
pkg_release="${RUN_NUMBER}"
|
||||
fi
|
||||
|
||||
echo "pkg_release=${pkg_release}" | tee -a "${GITHUB_OUTPUT}"
|
||||
69
.github/actions/setup-nix-env/action.yml
vendored
69
.github/actions/setup-nix-env/action.yml
vendored
@@ -1,69 +0,0 @@
|
||||
name: Setup Nix environment
|
||||
description: "Build the flake's CI environment and put its tools on PATH."
|
||||
|
||||
# The environment from nix/ci-env.nix, the same one the Linux CI images bake in
|
||||
# (see nix/docker). Exported onto PATH rather than entered with `nix develop`:
|
||||
# the composite actions below run plain `bash` and would escape a dev shell.
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
|
||||
steps:
|
||||
- name: Build the CI environment
|
||||
id: build
|
||||
shell: bash
|
||||
env:
|
||||
# --out-link doubles as a GC root for the length of the job.
|
||||
OUT_LINK: ${{ runner.temp }}/xrpld-ci-env
|
||||
run: |
|
||||
# --extra-experimental-features: flakes may not be on in the runner's nix.conf.
|
||||
nix --extra-experimental-features "nix-command flakes" \
|
||||
build .#default --out-link "${OUT_LINK}" --print-build-logs
|
||||
echo "path=$(readlink -f "${OUT_LINK}")" >>"${GITHUB_OUTPUT}"
|
||||
|
||||
- name: Export the environment
|
||||
shell: bash
|
||||
env:
|
||||
ENV_PATH: ${{ steps.build.outputs.path }}
|
||||
run: |
|
||||
echo "${ENV_PATH}/bin" >>"${GITHUB_PATH}"
|
||||
|
||||
# Already KEY=VALUE per line. See `darwinEnv` in nix/ci-env.nix.
|
||||
ENV_FILE="${ENV_PATH}/share/xrpld-ci-env/env"
|
||||
if [ -f "${ENV_FILE}" ]; then
|
||||
cat "${ENV_FILE}" >>"${GITHUB_ENV}"
|
||||
fi
|
||||
|
||||
# XrplSanity.cmake otherwise rejects a Nix compiler as one that leaked.
|
||||
echo "XRPL_DEVSHELL=ci-env" >>"${GITHUB_ENV}"
|
||||
|
||||
# Unlike the Linux nix images, macOS needs no SSL_CERT_FILE: it has its
|
||||
# own trust store, and pinning would break TLS to hosts relying on it.
|
||||
|
||||
# Workspace-local, so `cleanup-workspace` clears it, but not the
|
||||
# `.conan2` prepare-runner hands the system toolchain: that Conan is a
|
||||
# different version, and the two would migrate each other's cache.
|
||||
echo "CONAN_HOME=${{ github.workspace }}/.conan2-nix" >>"${GITHUB_ENV}"
|
||||
|
||||
# Config, profiles and remote, exactly as the dev shell sets them up on
|
||||
# entry; the `setup-conan` action is skipped for this toolchain.
|
||||
- name: Setup Conan
|
||||
shell: bash
|
||||
run: ./conan/init.sh
|
||||
|
||||
# `Check tools` runs later but swallows failures; a bad export would just
|
||||
# build with the system toolchain.
|
||||
- name: Verify the toolchain resolves into the Nix store
|
||||
shell: bash
|
||||
run: |
|
||||
for tool in clang clang++ cmake ninja conan; do
|
||||
path="$(command -v "${tool}" || true)"
|
||||
echo "${tool} -> ${path:-<not found>}"
|
||||
case "${path}" in
|
||||
/nix/store/*) ;;
|
||||
*)
|
||||
echo "::error::${tool} does not resolve into the Nix store"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
19
.github/dependabot.yml
vendored
19
.github/dependabot.yml
vendored
@@ -4,8 +4,7 @@ updates:
|
||||
directories:
|
||||
- /
|
||||
- .github/actions/build-deps/
|
||||
- .github/actions/cargo-cache/
|
||||
- .github/actions/release-info/
|
||||
- .github/actions/generate-version/
|
||||
- .github/actions/set-compiler-env/
|
||||
- .github/actions/setup-conan/
|
||||
schedule:
|
||||
@@ -20,19 +19,3 @@ updates:
|
||||
github-actions:
|
||||
patterns:
|
||||
- "*"
|
||||
|
||||
- package-ecosystem: cargo
|
||||
directory: /crates
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: monday
|
||||
time: "04:00"
|
||||
timezone: Etc/GMT
|
||||
commit-message:
|
||||
prefix: "chore: [DEPENDABOT] "
|
||||
target-branch: develop
|
||||
open-pull-requests-limit: 10
|
||||
groups:
|
||||
rust-dependencies:
|
||||
patterns:
|
||||
- "*"
|
||||
|
||||
2
.github/scripts/rename/binary.sh
vendored
2
.github/scripts/rename/binary.sh
vendored
@@ -49,7 +49,7 @@ ${SED_COMMAND} -i -E 's@ripple/xrpld@XRPLF/rippled@g' BUILD.md
|
||||
${SED_COMMAND} -i -E 's@XRPLF/xrpld@XRPLF/rippled@g' BUILD.md
|
||||
${SED_COMMAND} -i -E 's@xrpld \(`xrpld`\)@xrpld@g' BUILD.md
|
||||
${SED_COMMAND} -i -E 's@XRPLF/xrpld@XRPLF/rippled@g' CONTRIBUTING.md
|
||||
${SED_COMMAND} -i -E 's@XRPLF/xrpld@XRPLF/rippled@g' docs/install.md
|
||||
${SED_COMMAND} -i -E 's@XRPLF/xrpld@XRPLF/rippled@g' docs/build/install.md
|
||||
|
||||
popd
|
||||
echo "Processing complete."
|
||||
|
||||
4
.github/scripts/rename/docs.sh
vendored
4
.github/scripts/rename/docs.sh
vendored
@@ -77,8 +77,8 @@ ${SED_COMMAND} -i 's/Ripple integrators/XRPL developers/' README.md
|
||||
${SED_COMMAND} -i 's/sanitizer-configuration-for-rippled/sanitizer-configuration-for-xrpld/' docs/build/sanitizers.md
|
||||
${SED_COMMAND} -i 's/rippled/xrpld/g' .github/scripts/levelization/README.md
|
||||
${SED_COMMAND} -i 's/rippled/xrpld/g' .github/scripts/strategy-matrix/generate.py
|
||||
${SED_COMMAND} -i 's@/rippled@/xrpld@g' docs/install.md
|
||||
${SED_COMMAND} -i 's@github.com/XRPLF/xrpld@github.com/XRPLF/rippled@g' docs/install.md
|
||||
${SED_COMMAND} -i 's@/rippled@/xrpld@g' docs/build/install.md
|
||||
${SED_COMMAND} -i 's@github.com/XRPLF/xrpld@github.com/XRPLF/rippled@g' docs/build/install.md
|
||||
${SED_COMMAND} -i 's/rippled/xrpld/g' docs/Doxyfile
|
||||
${SED_COMMAND} -i 's/ripple_basics/basics/' include/xrpl/basics/CountedObject.h
|
||||
${SED_COMMAND} -i 's/<ripple/<xrpl/' include/xrpl/protocol/AccountID.h
|
||||
|
||||
20
.github/scripts/strategy-matrix/generate.py
vendored
20
.github/scripts/strategy-matrix/generate.py
vendored
@@ -7,13 +7,7 @@ from pathlib import Path
|
||||
|
||||
THIS_DIR = Path(__file__).parent.resolve()
|
||||
|
||||
_BASE_CMAKE_ARGS = [
|
||||
"-Dtests=ON",
|
||||
"-Dwerr=ON",
|
||||
"-Dxrpld=ON",
|
||||
"-Dwextra=ON",
|
||||
"-Drust=ON",
|
||||
]
|
||||
_BASE_CMAKE_ARGS = ["-Dtests=ON", "-Dwerr=ON", "-Dxrpld=ON", "-Dwextra=ON"]
|
||||
|
||||
# Maps sanitizer names (as used in cmake) to short config-name suffixes.
|
||||
_SANITIZER_SUFFIX: dict[str, str] = {
|
||||
@@ -94,9 +88,6 @@ class PlatformConfig:
|
||||
build_only: bool = False # if true, skip tests (e.g. macos/Windows Debug)
|
||||
benchmark: bool = False # if true, smoke-run the benchmarks after testing
|
||||
extra_cmake_args: str = ""
|
||||
# "" is the runner's system compiler, "nix" the flake's CI environment.
|
||||
# macOS only: Linux always builds in a Nix image, Windows has no Nix.
|
||||
toolchain: str = ""
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
if isinstance(self.build_type, str):
|
||||
@@ -146,7 +137,6 @@ class MatrixEntry:
|
||||
sanitizers: str
|
||||
image: str = "" # container image; empty for macOS/Windows (runs natively)
|
||||
compiler: str = "" # compiler name ("gcc" or "clang"); empty for macOS/Windows
|
||||
toolchain: str = "" # "nix" for the flake's CI environment; see PlatformConfig
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
@@ -225,7 +215,7 @@ def expand_linux_matrix(linux: LinuxFile, minimal: bool) -> list[MatrixEntry]:
|
||||
def expand_linux_packaging(linux: LinuxFile) -> list[PackagingEntry]:
|
||||
"""Generate the packaging matrix from a LinuxFile's package_configs section.
|
||||
|
||||
Packaging uses vanilla distro images (debian:bookworm, almalinux:9) instead of
|
||||
Packaging uses vanilla distro images (debian:bookworm, ubi9, …) instead of
|
||||
the nix-based build images, because deb/rpm tooling (debhelper, rpm-build)
|
||||
is taken from the distro's archive rather than from nixpkgs. Each config
|
||||
entry carries its own 'image'.
|
||||
@@ -263,12 +253,9 @@ def expand_platform_matrix(pf: PlatformFile, minimal: bool) -> list[MatrixEntry]
|
||||
if minimal and not cfg.minimal:
|
||||
continue
|
||||
for build_type in cfg.build_type:
|
||||
name = f"{platform_name}-{arch}-{build_type.lower()}"
|
||||
if cfg.toolchain:
|
||||
name += f"-{cfg.toolchain}"
|
||||
entries.append(
|
||||
MatrixEntry(
|
||||
config_name=name,
|
||||
config_name=f"{platform_name}-{arch}-{build_type.lower()}",
|
||||
cmake_args=get_cmake_args(build_type, cfg.extra_cmake_args),
|
||||
cmake_target="install" if is_windows else "all",
|
||||
build_only=cfg.build_only,
|
||||
@@ -276,7 +263,6 @@ def expand_platform_matrix(pf: PlatformFile, minimal: bool) -> list[MatrixEntry]
|
||||
build_type=build_type,
|
||||
architecture=Architecture(platform=pf.platform, runner=pf.runner),
|
||||
sanitizers="",
|
||||
toolchain=cfg.toolchain,
|
||||
)
|
||||
)
|
||||
return entries
|
||||
|
||||
6
.github/scripts/strategy-matrix/linux.json
vendored
6
.github/scripts/strategy-matrix/linux.json
vendored
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"image_tag": "sha-a0074f8",
|
||||
"image_tag": "sha-fecfc0c",
|
||||
"configs": {
|
||||
"ubuntu": [
|
||||
{
|
||||
@@ -92,7 +92,7 @@
|
||||
"build_type": ["Release"],
|
||||
"arch": ["amd64"],
|
||||
"minimal": false,
|
||||
"image": "ghcr.io/xrplf/xrpld/packaging-debian:sha-a6983f8"
|
||||
"image": "ghcr.io/xrplf/xrpld/packaging-debian:sha-577d745"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -102,7 +102,7 @@
|
||||
"build_type": ["Release"],
|
||||
"arch": ["amd64"],
|
||||
"minimal": false,
|
||||
"image": "ghcr.io/xrplf/xrpld/packaging-rhel:sha-a6983f8"
|
||||
"image": "ghcr.io/xrplf/xrpld/packaging-rhel:sha-577d745"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
13
.github/scripts/strategy-matrix/macos.json
vendored
13
.github/scripts/strategy-matrix/macos.json
vendored
@@ -12,19 +12,6 @@
|
||||
"extra_cmake_args": "-DCMAKE_POLICY_VERSION_MINIMUM=3.5",
|
||||
"build_only": true,
|
||||
"minimal": false
|
||||
},
|
||||
{
|
||||
"build_type": "Release",
|
||||
"extra_cmake_args": "-DCMAKE_POLICY_VERSION_MINIMUM=3.5",
|
||||
"toolchain": "nix",
|
||||
"minimal": false
|
||||
},
|
||||
{
|
||||
"build_type": "Debug",
|
||||
"extra_cmake_args": "-DCMAKE_POLICY_VERSION_MINIMUM=3.5",
|
||||
"toolchain": "nix",
|
||||
"build_only": true,
|
||||
"minimal": false
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
2
.github/workflows/build-nix-images.yml
vendored
2
.github/workflows/build-nix-images.yml
vendored
@@ -58,7 +58,7 @@ jobs:
|
||||
base_image: debian:bookworm
|
||||
- name: rhel
|
||||
base_image: registry.access.redhat.com/ubi9/ubi:latest
|
||||
uses: XRPLF/actions/.github/workflows/build-multiarch-image.yml@65d5a0bd72be4ecea95cff0673a6e0672ab5243a
|
||||
uses: XRPLF/actions/.github/workflows/build-multiarch-image.yml@9e7e4e80af9e684c116b38369add8eea64451f32
|
||||
with:
|
||||
image_name: xrpld/nix-${{ matrix.distro.name }}
|
||||
dockerfile: nix/docker/Dockerfile
|
||||
|
||||
5
.github/workflows/build-packaging-images.yml
vendored
5
.github/workflows/build-packaging-images.yml
vendored
@@ -36,10 +36,9 @@ jobs:
|
||||
distro:
|
||||
- name: debian
|
||||
base_image: debian:bookworm
|
||||
# AlmaLinux rather than UBI9, which does not ship rpm-sign.
|
||||
- name: rhel
|
||||
base_image: almalinux:9
|
||||
uses: XRPLF/actions/.github/workflows/build-multiarch-image.yml@65d5a0bd72be4ecea95cff0673a6e0672ab5243a
|
||||
base_image: registry.access.redhat.com/ubi9/ubi:latest
|
||||
uses: XRPLF/actions/.github/workflows/build-multiarch-image.yml@9e7e4e80af9e684c116b38369add8eea64451f32
|
||||
with:
|
||||
image_name: xrpld/packaging-${{ matrix.distro.name }}
|
||||
dockerfile: package/Dockerfile
|
||||
|
||||
2
.github/workflows/build-pre-commit-image.yml
vendored
2
.github/workflows/build-pre-commit-image.yml
vendored
@@ -30,7 +30,7 @@ jobs:
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
uses: XRPLF/actions/.github/workflows/build-multiarch-image.yml@65d5a0bd72be4ecea95cff0673a6e0672ab5243a
|
||||
uses: XRPLF/actions/.github/workflows/build-multiarch-image.yml@9e7e4e80af9e684c116b38369add8eea64451f32
|
||||
with:
|
||||
image_name: xrpld/pre-commit
|
||||
dockerfile: bin/pre-commit/Dockerfile
|
||||
|
||||
80
.github/workflows/cargo-audit.yml
vendored
80
.github/workflows/cargo-audit.yml
vendored
@@ -1,80 +0,0 @@
|
||||
name: Cargo audit
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# 06:32 UTC every Monday.
|
||||
- cron: "32 6 * * 1"
|
||||
push:
|
||||
branches:
|
||||
- "develop"
|
||||
- "release/*"
|
||||
paths:
|
||||
- "crates/**/Cargo.toml"
|
||||
- "crates/Cargo.lock"
|
||||
- ".github/workflows/cargo-audit.yml"
|
||||
pull_request:
|
||||
paths:
|
||||
- "crates/**/Cargo.toml"
|
||||
- "crates/Cargo.lock"
|
||||
- ".github/workflows/cargo-audit.yml"
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
working-directory: crates
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
audit:
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-a0074f8
|
||||
permissions:
|
||||
contents: read
|
||||
# Needed to open an issue on scheduled failures.
|
||||
issues: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Run cargo audit
|
||||
id: audit
|
||||
continue-on-error: true
|
||||
run: |
|
||||
set -o pipefail
|
||||
cargo audit | tee /tmp/cargo-audit.txt
|
||||
|
||||
- name: Prepare issue body
|
||||
if: ${{ steps.audit.outcome != 'success' && github.event_name == 'schedule' }}
|
||||
run: |
|
||||
{
|
||||
echo "## \`cargo audit\` found advisories"
|
||||
echo
|
||||
echo '```'
|
||||
cat /tmp/cargo-audit.txt
|
||||
echo '```'
|
||||
echo
|
||||
echo "---"
|
||||
echo "*This issue was automatically created by the cargo-audit workflow.*"
|
||||
} >/tmp/cargo-audit-issue.md
|
||||
|
||||
- name: Create issue
|
||||
if: ${{ steps.audit.outcome != 'success' && github.event_name == 'schedule' }}
|
||||
uses: XRPLF/actions/create-issue@2b8bc36af85b88bca0dd7bfac2e2dc05f94ad712
|
||||
with:
|
||||
title: "cargo audit found vulnerabilities"
|
||||
body_file: /tmp/cargo-audit-issue.md
|
||||
labels: "Bug,Security"
|
||||
|
||||
- name: Fail if advisories were found
|
||||
if: ${{ steps.audit.outcome != 'success' }}
|
||||
run: |
|
||||
echo "cargo audit found advisories!"
|
||||
cat /tmp/cargo-audit.txt
|
||||
exit 1
|
||||
2
.github/workflows/check-tools.yml
vendored
2
.github/workflows/check-tools.yml
vendored
@@ -79,7 +79,7 @@ jobs:
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Prepare runner
|
||||
uses: XRPLF/actions/prepare-runner@7bf7ceca5932114abdd0d43493c3c30c5a654e13
|
||||
uses: XRPLF/actions/prepare-runner@c00c22ada3bd6bcda48fcb0d62fbbab49fec8a0f
|
||||
with:
|
||||
enable_ccache: false
|
||||
|
||||
|
||||
17
.github/workflows/on-pr.yml
vendored
17
.github/workflows/on-pr.yml
vendored
@@ -77,28 +77,24 @@ jobs:
|
||||
|
||||
# Keep the paths below in sync with those in `on-trigger.yml`.
|
||||
.github/actions/build-deps/**
|
||||
.github/actions/release-info/**
|
||||
.github/actions/generate-version/**
|
||||
.github/actions/setup-conan/**
|
||||
.github/actions/setup-nix-env/**
|
||||
.github/scripts/strategy-matrix/**
|
||||
.github/workflows/reusable-build-test-config.yml
|
||||
.github/workflows/reusable-build-test.yml
|
||||
.github/workflows/reusable-check-autogen.yml
|
||||
.github/workflows/reusable-clang-tidy.yml
|
||||
.github/workflows/reusable-package.yml
|
||||
.github/workflows/reusable-rust.yml
|
||||
.github/workflows/reusable-strategy-matrix.yml
|
||||
.github/workflows/reusable-test.yml
|
||||
.github/workflows/reusable-upload-recipe.yml
|
||||
.clang-tidy
|
||||
.codecov.yml
|
||||
bin/check-nix-store-refs.sh
|
||||
bin/check-tools.sh
|
||||
bin/default-loader-path.sh
|
||||
cfg/**
|
||||
cmake/**
|
||||
conan/**
|
||||
crates/**
|
||||
external/**
|
||||
include/**
|
||||
src/**
|
||||
@@ -106,9 +102,6 @@ jobs:
|
||||
CMakeLists.txt
|
||||
conanfile.py
|
||||
conan.lock
|
||||
flake.lock
|
||||
flake.nix
|
||||
nix/**
|
||||
LICENSE.md
|
||||
package/**
|
||||
README.md
|
||||
@@ -175,13 +168,6 @@ jobs:
|
||||
secrets:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
rust:
|
||||
needs: should-run
|
||||
if: ${{ needs.should-run.outputs.go == 'true' }}
|
||||
uses: ./.github/workflows/reusable-rust.yml
|
||||
secrets:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
package:
|
||||
needs: [should-run, build-test]
|
||||
# Packaging consumes the debian/rhel release binaries, which are only built
|
||||
@@ -225,7 +211,6 @@ jobs:
|
||||
- check-rename
|
||||
- clang-tidy
|
||||
- build-test
|
||||
- rust
|
||||
- package
|
||||
- upload-recipe
|
||||
- notify-clio
|
||||
|
||||
18
.github/workflows/on-tag.yml
vendored
18
.github/workflows/on-tag.yml
vendored
@@ -1,9 +1,5 @@
|
||||
# When a versioned tag is pushed, this workflow:
|
||||
#
|
||||
# - uploads the libxrpl recipe to the Conan remote
|
||||
# - builds and tests the release binaries
|
||||
# - builds the DEB and RPM packages
|
||||
# - publishes those packages to the XRPLF package repositories
|
||||
# This workflow uploads the libxrpl recipe to the Conan remote and builds
|
||||
# release packages when a versioned tag is pushed.
|
||||
name: Tag
|
||||
|
||||
on:
|
||||
@@ -28,7 +24,7 @@ jobs:
|
||||
remote_password: ${{ secrets.NEXUS_REMOTE_PASSWORD }}
|
||||
|
||||
build-test:
|
||||
if: ${{ github.repository_owner == 'XRPLF' }}
|
||||
if: ${{ github.repository == 'XRPLF/rippled' }}
|
||||
uses: ./.github/workflows/reusable-build-test.yml
|
||||
strategy:
|
||||
fail-fast: true
|
||||
@@ -41,12 +37,6 @@ jobs:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
package:
|
||||
if: ${{ github.repository_owner == 'XRPLF' }}
|
||||
if: ${{ github.repository == 'XRPLF/rippled' }}
|
||||
needs: build-test
|
||||
uses: ./.github/workflows/reusable-package.yml
|
||||
with:
|
||||
publish: true
|
||||
secrets:
|
||||
remote_username: ${{ secrets.NEXUS_REMOTE_USERNAME }}
|
||||
remote_password: ${{ secrets.NEXUS_REMOTE_PASSWORD }}
|
||||
signing_key: ${{ secrets.NEXUS_PACKAGES_PRIVATE_KEY }}
|
||||
|
||||
22
.github/workflows/on-trigger.yml
vendored
22
.github/workflows/on-trigger.yml
vendored
@@ -15,28 +15,24 @@ on:
|
||||
|
||||
# Keep the paths below in sync with those in `on-pr.yml`.
|
||||
- ".github/actions/build-deps/**"
|
||||
- ".github/actions/release-info/**"
|
||||
- ".github/actions/generate-version/**"
|
||||
- ".github/actions/setup-conan/**"
|
||||
- ".github/actions/setup-nix-env/**"
|
||||
- ".github/scripts/strategy-matrix/**"
|
||||
- ".github/workflows/reusable-build-test-config.yml"
|
||||
- ".github/workflows/reusable-build-test.yml"
|
||||
- ".github/workflows/reusable-check-autogen.yml"
|
||||
- ".github/workflows/reusable-clang-tidy.yml"
|
||||
- ".github/workflows/reusable-package.yml"
|
||||
- ".github/workflows/reusable-rust.yml"
|
||||
- ".github/workflows/reusable-strategy-matrix.yml"
|
||||
- ".github/workflows/reusable-test.yml"
|
||||
- ".github/workflows/reusable-upload-recipe.yml"
|
||||
- ".clang-tidy"
|
||||
- ".codecov.yml"
|
||||
- "bin/check-nix-store-refs.sh"
|
||||
- "bin/check-tools.sh"
|
||||
- "bin/default-loader-path.sh"
|
||||
- "cfg/**"
|
||||
- "cmake/**"
|
||||
- "conan/**"
|
||||
- "crates/**"
|
||||
- "external/**"
|
||||
- "include/**"
|
||||
- "src/**"
|
||||
@@ -44,9 +40,6 @@ on:
|
||||
- "CMakeLists.txt"
|
||||
- "conanfile.py"
|
||||
- "conan.lock"
|
||||
- "flake.lock"
|
||||
- "flake.nix"
|
||||
- "nix/**"
|
||||
- "LICENSE.md"
|
||||
- "package/**"
|
||||
- "README.md"
|
||||
@@ -103,11 +96,6 @@ jobs:
|
||||
secrets:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
rust:
|
||||
uses: ./.github/workflows/reusable-rust.yml
|
||||
secrets:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
upload-recipe:
|
||||
needs: build-test
|
||||
# Only run when pushing to the develop branch.
|
||||
@@ -120,11 +108,3 @@ jobs:
|
||||
package:
|
||||
needs: build-test
|
||||
uses: ./.github/workflows/reusable-package.yml
|
||||
with:
|
||||
# Packages are built on every trigger; only develop pushes in XRPLF/rippled
|
||||
# publish them, matching upload-recipe above.
|
||||
publish: ${{ github.repository == 'XRPLF/rippled' && github.event_name == 'push' && github.ref == 'refs/heads/develop' }}
|
||||
secrets:
|
||||
remote_username: ${{ secrets.NEXUS_REMOTE_USERNAME }}
|
||||
remote_password: ${{ secrets.NEXUS_REMOTE_PASSWORD }}
|
||||
signing_key: ${{ secrets.NEXUS_PACKAGES_PRIVATE_KEY }}
|
||||
|
||||
2
.github/workflows/pre-commit.yml
vendored
2
.github/workflows/pre-commit.yml
vendored
@@ -14,7 +14,7 @@ on:
|
||||
jobs:
|
||||
# Call the workflow in the XRPLF/actions repo that runs the pre-commit hooks.
|
||||
run-hooks:
|
||||
uses: XRPLF/actions/.github/workflows/pre-commit.yml@f1952595d212e86169935135efc66294b4574131
|
||||
uses: XRPLF/actions/.github/workflows/pre-commit.yml@3ba08d6ddf114092891d48491fc2e26c3ba15552
|
||||
with:
|
||||
runs_on: ubuntu-latest
|
||||
container: '{ "image": "ghcr.io/xrplf/xrpld/pre-commit:sha-f56b79f" }'
|
||||
|
||||
4
.github/workflows/publish-docs.yml
vendored
4
.github/workflows/publish-docs.yml
vendored
@@ -41,13 +41,13 @@ env:
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-a0074f8
|
||||
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-fecfc0c
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Prepare runner
|
||||
uses: XRPLF/actions/prepare-runner@7bf7ceca5932114abdd0d43493c3c30c5a654e13
|
||||
uses: XRPLF/actions/prepare-runner@c00c22ada3bd6bcda48fcb0d62fbbab49fec8a0f
|
||||
with:
|
||||
enable_ccache: false
|
||||
|
||||
|
||||
59
.github/workflows/reusable-build-test-config.yml
vendored
59
.github/workflows/reusable-build-test-config.yml
vendored
@@ -69,12 +69,6 @@ on:
|
||||
type: string
|
||||
default: ""
|
||||
|
||||
toolchain:
|
||||
description: 'Where the toolchain comes from ("nix" to build the flake CI environment on the runner, empty for the system one). macOS only: Linux always builds in a Nix image, and Nix has no Windows support.'
|
||||
required: false
|
||||
type: string
|
||||
default: ""
|
||||
|
||||
secrets:
|
||||
CODECOV_TOKEN:
|
||||
description: "The Codecov token to use for uploading coverage reports."
|
||||
@@ -117,9 +111,6 @@ jobs:
|
||||
VOIDSTAR_ENABLED: ${{ contains(inputs.cmake_args, '-Dvoidstar=ON') }}
|
||||
VALIDATOR_KEYS_ENABLED: ${{ contains(inputs.cmake_args, '-Dvalidator_keys=ON') }}
|
||||
SANITIZERS_ENABLED: ${{ inputs.sanitizers != '' }}
|
||||
# The binaries reusable-package.yml consumes. A private repository skips
|
||||
# them except on a tag push, which is what produces its release packages.
|
||||
PACKAGING_ARTIFACTS_ENABLED: ${{ github.event.repository.visibility == 'public' || startsWith(github.ref, 'refs/tags/') }}
|
||||
steps:
|
||||
- name: Cleanup workspace (macOS and Windows)
|
||||
if: ${{ runner.os == 'macOS' || runner.os == 'Windows' }}
|
||||
@@ -129,15 +120,10 @@ jobs:
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Prepare runner
|
||||
uses: XRPLF/actions/prepare-runner@7bf7ceca5932114abdd0d43493c3c30c5a654e13
|
||||
uses: XRPLF/actions/prepare-runner@c00c22ada3bd6bcda48fcb0d62fbbab49fec8a0f
|
||||
with:
|
||||
enable_ccache: ${{ inputs.ccache_enabled }}
|
||||
|
||||
# Before any step that uses a build tool, composite actions included.
|
||||
- name: Setup Nix environment
|
||||
if: ${{ inputs.toolchain == 'nix' }}
|
||||
uses: ./.github/actions/setup-nix-env
|
||||
|
||||
- name: Set ccache log file
|
||||
if: ${{ inputs.ccache_enabled && runner.debug == '1' }}
|
||||
run: echo "CCACHE_LOGFILE=${{ runner.temp }}/ccache.log" >>"${GITHUB_ENV}"
|
||||
@@ -162,22 +148,7 @@ jobs:
|
||||
with:
|
||||
compiler: ${{ inputs.compiler }}
|
||||
|
||||
- name: Use cargo artifacts cache
|
||||
uses: ./.github/actions/cargo-cache
|
||||
with:
|
||||
cache-directories: ${{ env.BUILD_DIR }}/corrosion
|
||||
key: ${{ inputs.config_name }}
|
||||
save-if: ${{ github.ref == 'refs/heads/develop' || startsWith(github.ref, 'refs/heads/release') }}
|
||||
# two workspaces here because build artifacts are located in 2 places:
|
||||
# - crates/target when cargo is called directly
|
||||
# - build/cargo when cargo is called by cmake
|
||||
workspaces: |
|
||||
crates
|
||||
crates -> ${{ runner.os == 'Windows' && format('../{0}/x64/{1}/cargo', env.BUILD_DIR, inputs.build_type) || format('../{0}/cargo', env.BUILD_DIR) }}
|
||||
|
||||
# `setup-nix-env` already did this for the Nix toolchain.
|
||||
- name: Setup Conan
|
||||
if: ${{ inputs.toolchain != 'nix' }}
|
||||
env:
|
||||
SANITIZERS: ${{ inputs.sanitizers }}
|
||||
uses: ./.github/actions/setup-conan
|
||||
@@ -241,24 +212,6 @@ jobs:
|
||||
--target "${CMAKE_TARGET}" \
|
||||
2>&1 | tee "${GITHUB_WORKSPACE}/build.log"
|
||||
|
||||
# Nothing may reference the store, so whole trees are checked - the Conan
|
||||
# cache included, since what it holds is what gets uploaded and reused.
|
||||
- name: Check the build output for Nix store references (Nix toolchain)
|
||||
if: ${{ inputs.toolchain == 'nix' }}
|
||||
run: ./bin/check-nix-store-refs.sh "${BUILD_DIR}"
|
||||
|
||||
- name: Check the Conan cache for Nix store references (Nix toolchain)
|
||||
if: ${{ inputs.toolchain == 'nix' }}
|
||||
run: ./bin/check-nix-store-refs.sh "${CONAN_HOME}"
|
||||
|
||||
# Only what PatchNixBinary.cmake retargets: the toolchain in the Linux
|
||||
# images always references the store. Same condition it uses.
|
||||
- name: Check for Nix store references (Linux)
|
||||
if: ${{ runner.os == 'Linux' && env.SANITIZERS_ENABLED == 'false' }}
|
||||
run: |
|
||||
./bin/check-nix-store-refs.sh "${BUILD_DIR}/xrpld"
|
||||
./bin/check-nix-store-refs.sh "${BUILD_DIR}/xrpl_tests"
|
||||
|
||||
- name: Show ccache statistics
|
||||
if: ${{ inputs.ccache_enabled }}
|
||||
run: |
|
||||
@@ -269,7 +222,7 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Upload the binary (Linux)
|
||||
if: ${{ env.PACKAGING_ARTIFACTS_ENABLED == 'true' && runner.os == 'Linux' }}
|
||||
if: ${{ github.event.repository.visibility == 'public' && runner.os == 'Linux' }}
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: xrpld-${{ inputs.config_name }}
|
||||
@@ -283,7 +236,7 @@ jobs:
|
||||
run: ./validator-keys --unittest
|
||||
|
||||
- name: Upload the validator-keys binary
|
||||
if: ${{ env.PACKAGING_ARTIFACTS_ENABLED == 'true' && env.VALIDATOR_KEYS_ENABLED == 'true' }}
|
||||
if: ${{ github.event.repository.visibility == 'public' && env.VALIDATOR_KEYS_ENABLED == 'true' }}
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: validator-keys-${{ inputs.config_name }}
|
||||
@@ -370,11 +323,6 @@ jobs:
|
||||
|
||||
LD_PRELOAD="$PRELOAD" ./xrpld --unittest --unittest-jobs "${BUILD_NPROC}" 2>&1 | tee "${GITHUB_WORKSPACE}/unittest.log"
|
||||
|
||||
- name: Run Rust tests
|
||||
if: ${{ !inputs.build_only }}
|
||||
working-directory: crates
|
||||
run: cargo nextest run --workspace --all-features --locked --no-tests=warn
|
||||
|
||||
# Smoke-run every benchmark module with a single repetition to confirm the
|
||||
# benchmarks still build and execute. This is a correctness check, not a
|
||||
# performance measurement, so there is nothing to gain from repeating it
|
||||
@@ -446,7 +394,6 @@ jobs:
|
||||
disable_telem: true
|
||||
fail_ci_if_error: true
|
||||
files: ${{ env.BUILD_DIR }}/coverage.xml
|
||||
flags: cpp
|
||||
plugins: noop
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
verbose: true
|
||||
|
||||
1
.github/workflows/reusable-build-test.yml
vendored
1
.github/workflows/reusable-build-test.yml
vendored
@@ -51,6 +51,5 @@ jobs:
|
||||
config_name: ${{ matrix.config_name }}
|
||||
sanitizers: ${{ matrix.sanitizers }}
|
||||
compiler: ${{ matrix.compiler || '' }}
|
||||
toolchain: ${{ matrix.toolchain || '' }}
|
||||
secrets:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
19
.github/workflows/reusable-clang-tidy.yml
vendored
19
.github/workflows/reusable-clang-tidy.yml
vendored
@@ -27,14 +27,14 @@ jobs:
|
||||
determine-files:
|
||||
permissions:
|
||||
contents: read
|
||||
uses: XRPLF/actions/.github/workflows/determine-tidy-files.yml@70145243b905dc3e040a61d39c00e178cfb96f71
|
||||
uses: XRPLF/actions/.github/workflows/determine-tidy-files.yml@d041ac9f1fa9f07a4ba335eb4c1c82233fb3fef6
|
||||
|
||||
run-clang-tidy:
|
||||
name: Run clang tidy
|
||||
needs: [determine-files]
|
||||
if: ${{ needs.determine-files.outputs.cpp_changed_files != '' || needs.determine-files.outputs.need_full_run == 'true' }}
|
||||
runs-on: ["self-hosted", "Linux", "X64", "heavy"]
|
||||
container: "ghcr.io/xrplf/xrpld/nix-debian:sha-a0074f8"
|
||||
container: "ghcr.io/xrplf/xrpld/nix-debian:sha-fecfc0c"
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
@@ -43,7 +43,7 @@ jobs:
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Prepare runner
|
||||
uses: XRPLF/actions/prepare-runner@7bf7ceca5932114abdd0d43493c3c30c5a654e13
|
||||
uses: XRPLF/actions/prepare-runner@c00c22ada3bd6bcda48fcb0d62fbbab49fec8a0f
|
||||
with:
|
||||
enable_ccache: false
|
||||
|
||||
@@ -59,13 +59,6 @@ jobs:
|
||||
with:
|
||||
compiler: ${{ env.COMPILER }}
|
||||
|
||||
- name: Use cargo artifacts cache
|
||||
uses: ./.github/actions/cargo-cache
|
||||
with:
|
||||
cache-directories: ${{ env.BUILD_DIR }}/corrosion
|
||||
save-if: ${{ github.ref == 'refs/heads/develop' || startsWith(github.ref, 'refs/heads/release') }}
|
||||
workspaces: crates -> ../${{ env.BUILD_DIR }}/cargo
|
||||
|
||||
- name: Setup Conan
|
||||
uses: ./.github/actions/setup-conan
|
||||
|
||||
@@ -87,13 +80,13 @@ jobs:
|
||||
-Dwerr=ON \
|
||||
-Dxrpld=ON \
|
||||
-Dverify_headers=ON \
|
||||
-Drust=ON \
|
||||
..
|
||||
|
||||
- name: Build clang-tidy prerequisites
|
||||
# clang-tidy needs headers generated from proto files
|
||||
- name: Build libxrpl.libpb
|
||||
working-directory: ${{ env.BUILD_DIR }}
|
||||
run: |
|
||||
ninja -j ${{ steps.nproc.outputs.nproc }} tidy_prerequisites
|
||||
ninja -j ${{ steps.nproc.outputs.nproc }} xrpl.libpb
|
||||
|
||||
- name: Run clang tidy
|
||||
id: run_clang_tidy
|
||||
|
||||
60
.github/workflows/reusable-package.yml
vendored
60
.github/workflows/reusable-package.yml
vendored
@@ -1,37 +1,17 @@
|
||||
# Build Linux packages from the pre-built xrpld and validator-keys artifacts:
|
||||
#
|
||||
# - one job per distro, taken from "package_configs" in linux.json
|
||||
# - each job runs in that distro's container, which is what decides DEB or RPM
|
||||
# - with 'publish: true' a job also uploads what it built
|
||||
# (see package/publish_pkg.sh)
|
||||
#
|
||||
# Only linux/amd64 is supported; the runner is hardcoded in the job below.
|
||||
# Build Linux packages (DEB and RPM) from pre-built binary artifacts (xrpld and
|
||||
# validator-keys). Discovers which configurations to package from linux.json
|
||||
# (configs in "package_configs") and fans out one job per distro. Only
|
||||
# linux/amd64 is supported; the runner is hardcoded in the job below.
|
||||
name: Package
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
publish:
|
||||
description: "Whether to publish the packages after building them."
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
nexus_url:
|
||||
description: "The base URL of the Nexus instance hosting the deb and rpm repositories."
|
||||
pkg_release:
|
||||
description: "Package release number. Increment when repackaging the same executable."
|
||||
required: false
|
||||
type: string
|
||||
default: https://packages.xrplf.org
|
||||
|
||||
secrets:
|
||||
remote_username:
|
||||
description: "The username of a Nexus account with write access to the repositories."
|
||||
required: false
|
||||
remote_password:
|
||||
description: "The password or token for that Nexus account."
|
||||
required: false
|
||||
signing_key:
|
||||
description: "Armoured PGP private key used to sign the RPMs. Required when publishing."
|
||||
required: false
|
||||
default: "1"
|
||||
|
||||
defaults:
|
||||
run:
|
||||
@@ -61,7 +41,7 @@ jobs:
|
||||
|
||||
package:
|
||||
needs: [generate-matrix]
|
||||
if: ${{ github.event.repository.visibility == 'public' || startsWith(github.ref, 'refs/tags/') }}
|
||||
if: ${{ github.event.repository.visibility == 'public' }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}
|
||||
@@ -91,24 +71,11 @@ jobs:
|
||||
- name: Make binaries executable
|
||||
run: chmod +x "${BUILD_DIR}/xrpld" "${BUILD_DIR}/validator-keys"
|
||||
|
||||
- name: Determine release info
|
||||
id: release_info
|
||||
uses: ./.github/actions/release-info
|
||||
|
||||
- name: Build package
|
||||
env:
|
||||
PKG_RELEASE: ${{ steps.release_info.outputs.pkg_release }}
|
||||
PKG_CHANNEL: ${{ steps.release_info.outputs.channel }}
|
||||
PKG_RELEASE: ${{ inputs.pkg_release }}
|
||||
run: ./package/build_pkg.sh
|
||||
|
||||
# Before the upload, so the artifact and the published package are the
|
||||
# same bytes. DEBs are not signed, so the key is never set on that job.
|
||||
- name: Sign RPM
|
||||
if: ${{ inputs.publish && matrix.distro == 'rhel' }}
|
||||
env:
|
||||
PKG_SIGNING_KEY: ${{ secrets.signing_key }}
|
||||
run: ./package/sign_rpm.sh "${BUILD_DIR}"
|
||||
|
||||
- name: Upload package artifact
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
@@ -118,12 +85,3 @@ jobs:
|
||||
${{ env.BUILD_DIR }}/debbuild/*.ddeb
|
||||
${{ env.BUILD_DIR }}/rpmbuild/RPMS/**/*.rpm
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Publish package
|
||||
if: ${{ inputs.publish }}
|
||||
env:
|
||||
CHANNEL: ${{ steps.release_info.outputs.channel }}
|
||||
NEXUS_URL: ${{ inputs.nexus_url }}
|
||||
NEXUS_USERNAME: ${{ secrets.remote_username }}
|
||||
NEXUS_PASSWORD: ${{ secrets.remote_password }}
|
||||
run: ./package/publish_pkg.sh "${CHANNEL}" "${BUILD_DIR}"
|
||||
|
||||
80
.github/workflows/reusable-rust.yml
vendored
80
.github/workflows/reusable-rust.yml
vendored
@@ -1,80 +0,0 @@
|
||||
# Clippy, coverage and documentation for the Rust crates in crates/. Each runs
|
||||
# as an independent job on a GitHub-hosted runner, but inside the same container
|
||||
# image used to build the crates in the C++/Corrosion path, so the toolchain
|
||||
# (and therefore the lints, coverage instrumentation and the cargo cache) matches
|
||||
# what production builds use.
|
||||
#
|
||||
# Rust unit tests are deliberately NOT run here. They run as part of the C++
|
||||
# build (reusable-build-test-config.yml), which already compiles the crates on a
|
||||
# self-hosted runner, so there is no need to provision a toolchain again.
|
||||
name: Rust
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
secrets:
|
||||
CODECOV_TOKEN:
|
||||
description: "The Codecov token to use for uploading coverage reports."
|
||||
required: true
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
working-directory: crates
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
clippy:
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-a0074f8
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Use cargo artifacts cache
|
||||
uses: ./.github/actions/cargo-cache
|
||||
|
||||
- name: Run clippy
|
||||
run: cargo clippy --workspace --all-targets --all-features --locked -- -D warnings
|
||||
|
||||
coverage:
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-a0074f8
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Use cargo artifacts cache
|
||||
uses: ./.github/actions/cargo-cache
|
||||
|
||||
- name: Generate coverage report
|
||||
run: cargo llvm-cov nextest --workspace --all-features --locked --no-tests=warn --lcov --output-path lcov.info
|
||||
|
||||
- name: Upload coverage report
|
||||
if: ${{ github.repository == 'XRPLF/rippled' }}
|
||||
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
|
||||
with:
|
||||
disable_search: true
|
||||
disable_telem: true
|
||||
fail_ci_if_error: true
|
||||
files: crates/lcov.info
|
||||
flags: rust
|
||||
plugins: noop
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
verbose: true
|
||||
|
||||
doc:
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-a0074f8
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Use cargo artifacts cache
|
||||
uses: ./.github/actions/cargo-cache
|
||||
|
||||
- name: Build documentation
|
||||
env:
|
||||
RUSTDOCFLAGS: "-D warnings"
|
||||
run: cargo doc --workspace --no-deps --all-features --locked
|
||||
14
.github/workflows/reusable-upload-recipe.yml
vendored
14
.github/workflows/reusable-upload-recipe.yml
vendored
@@ -40,7 +40,7 @@ defaults:
|
||||
jobs:
|
||||
upload:
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-a0074f8
|
||||
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-fecfc0c
|
||||
env:
|
||||
REMOTE_NAME: ${{ inputs.remote_name }}
|
||||
CONAN_LOGIN_USERNAME_XRPLF: ${{ secrets.remote_username }}
|
||||
@@ -49,9 +49,9 @@ jobs:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Determine release info
|
||||
id: release_info
|
||||
uses: ./.github/actions/release-info
|
||||
- name: Generate build version number
|
||||
id: version
|
||||
uses: ./.github/actions/generate-version
|
||||
|
||||
- name: Set up Conan
|
||||
uses: ./.github/actions/setup-conan
|
||||
@@ -64,8 +64,8 @@ jobs:
|
||||
|
||||
- name: Upload Conan recipe (version)
|
||||
run: |
|
||||
conan export . --version=${{ steps.release_info.outputs.version }}
|
||||
conan upload --confirm --check --remote="${REMOTE_NAME}" xrpl/${{ steps.release_info.outputs.version }}
|
||||
conan export . --version=${{ steps.version.outputs.version }}
|
||||
conan upload --confirm --check --remote="${REMOTE_NAME}" xrpl/${{ steps.version.outputs.version }}
|
||||
|
||||
# When this workflow is triggered by a push event, it will always be when merging into the
|
||||
# 'develop' branch, see on-trigger.yml.
|
||||
@@ -92,4 +92,4 @@ jobs:
|
||||
conan upload --confirm --check --remote="${REMOTE_NAME}" xrpl/release
|
||||
|
||||
outputs:
|
||||
ref: xrpl/${{ steps.release_info.outputs.version }}
|
||||
ref: xrpl/${{ steps.version.outputs.version }}
|
||||
|
||||
13
.github/workflows/upload-conan-deps.yml
vendored
13
.github/workflows/upload-conan-deps.yml
vendored
@@ -68,15 +68,10 @@ jobs:
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Prepare runner
|
||||
uses: XRPLF/actions/prepare-runner@7bf7ceca5932114abdd0d43493c3c30c5a654e13
|
||||
uses: XRPLF/actions/prepare-runner@c00c22ada3bd6bcda48fcb0d62fbbab49fec8a0f
|
||||
with:
|
||||
enable_ccache: false
|
||||
|
||||
# Before any step that uses a build tool, composite actions included.
|
||||
- name: Setup Nix environment
|
||||
if: ${{ matrix.toolchain == 'nix' }}
|
||||
uses: ./.github/actions/setup-nix-env
|
||||
|
||||
- name: Print build environment
|
||||
uses: XRPLF/actions/print-build-env@59dec886e4afb05a1724443af08baccbc045b574
|
||||
|
||||
@@ -92,9 +87,7 @@ jobs:
|
||||
with:
|
||||
compiler: ${{ matrix.compiler }}
|
||||
|
||||
# `setup-nix-env` already did this for the Nix toolchain.
|
||||
- name: Setup Conan
|
||||
if: ${{ matrix.toolchain != 'nix' }}
|
||||
env:
|
||||
SANITIZERS: ${{ matrix.sanitizers }}
|
||||
uses: ./.github/actions/setup-conan
|
||||
@@ -113,10 +106,6 @@ jobs:
|
||||
log_verbosity: ${{ runner.os == 'Windows' && 'quiet' || 'verbose' }}
|
||||
sanitizers: ${{ matrix.sanitizers }}
|
||||
|
||||
- name: Check the Conan cache for Nix store references (Nix toolchain)
|
||||
if: ${{ matrix.toolchain == 'nix' }}
|
||||
run: ./bin/check-nix-store-refs.sh "${CONAN_HOME}"
|
||||
|
||||
- name: Log into Conan remote
|
||||
if: ${{ github.repository == 'XRPLF/rippled' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') }}
|
||||
run: conan remote login "${CONAN_REMOTE_NAME}" "${{ secrets.NEXUS_REMOTE_USERNAME }}" --password "${{ secrets.NEXUS_REMOTE_PASSWORD }}"
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -89,6 +89,3 @@ target/
|
||||
|
||||
# clangd cache
|
||||
/.cache
|
||||
|
||||
# Rust build directory
|
||||
crates/target
|
||||
|
||||
@@ -62,15 +62,6 @@ repos:
|
||||
types_or: [c++, c, proto]
|
||||
exclude: ^include/xrpl/protocol_autogen/(transactions|ledger_entries)/
|
||||
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: cargo-fmt
|
||||
name: cargo fmt
|
||||
entry: cargo fmt --manifest-path crates/Cargo.toml --all
|
||||
language: system
|
||||
types: [rust]
|
||||
pass_filenames: false # rustfmt formats the whole workspace
|
||||
|
||||
- repo: https://github.com/BlankSpruce/gersemi-pre-commit
|
||||
rev: e98930bdc210d3387007f9252d8c1694ea7e410f # frozen: 0.27.7
|
||||
hooks:
|
||||
|
||||
25
BUILD.md
25
BUILD.md
@@ -304,7 +304,6 @@ See [Sanitizers docs](./docs/build/sanitizers.md) for more details.
|
||||
| ---------------- | ------------- | ----------------------------------------------------------------------------- |
|
||||
| `assert` | OFF | Force enabling assertions. |
|
||||
| `coverage` | OFF | Prepare the coverage report. |
|
||||
| `rust` | OFF | Build the Rust crates and the C++ code that depends on them. |
|
||||
| `tests` | OFF | Build tests. |
|
||||
| `unity` | OFF | Configure a unity build. |
|
||||
| `verify_headers` | ON | Make the `verify-headers` target available to compile each header on its own. |
|
||||
@@ -317,30 +316,6 @@ memory) since they concatenate sources into fewer translation units. Non-unity
|
||||
builds may be faster for incremental builds, and can be helpful for detecting
|
||||
`#include` omissions.
|
||||
|
||||
### Rust crates
|
||||
|
||||
The Rust crates in `crates/` are only part of the build when `rust` is ON. With
|
||||
`-Drust=OFF` (the default) the `crates` directory is not added to the build, no
|
||||
cxxbridge bindings are generated, and the C++ tests that exercise the Rust
|
||||
interop are not compiled — so no Rust toolchain is needed. CI builds always pass
|
||||
`-Drust=ON`.
|
||||
|
||||
With `-Drust=ON` you need one extra dependency: a Rust toolchain (`cargo`,
|
||||
`rustc`) matching the channel pinned in
|
||||
[`rust-toolchain.toml`](./rust-toolchain.toml), which compiles the crates and
|
||||
generates the cxxbridge bindings. It is provided by the
|
||||
[Nix development shell](./docs/build/nix.md), so `-Drust=ON` works there without
|
||||
any extra setup; otherwise install it as described in
|
||||
[Rust](./docs/build/environment.md#rust).
|
||||
|
||||
The crates also have their own Rust unit tests. Those are run with `cargo` and
|
||||
need only the Rust toolchain, independently of CMake and of the `rust` option
|
||||
(CI runs them with `cargo nextest`):
|
||||
|
||||
```bash
|
||||
cargo test --manifest-path crates/Cargo.toml --workspace
|
||||
```
|
||||
|
||||
### Verifying headers
|
||||
|
||||
The regular build only compiles `.cpp` files, so a header is only ever checked
|
||||
|
||||
@@ -114,7 +114,6 @@ find_package(OpenSSL REQUIRED)
|
||||
find_package(secp256k1 REQUIRED)
|
||||
find_package(SOCI REQUIRED)
|
||||
find_package(SQLite3 REQUIRED)
|
||||
find_package(wasmi REQUIRED)
|
||||
find_package(xxHash REQUIRED)
|
||||
|
||||
target_link_libraries(
|
||||
@@ -159,13 +158,7 @@ if(coverage)
|
||||
include(XrplCov)
|
||||
endif()
|
||||
|
||||
add_custom_target(tidy_prerequisites)
|
||||
|
||||
if(rust)
|
||||
add_subdirectory(crates)
|
||||
endif()
|
||||
include(XrplCore)
|
||||
|
||||
include(XrplProtocolAutogen)
|
||||
include(XrplInstall)
|
||||
include(XrplValidatorKeys)
|
||||
|
||||
@@ -225,9 +225,8 @@ environment, so you don't need to install most of the individual tools
|
||||
yourself. The version of each hook sourced from an external repository
|
||||
(`clang-format`, `gersemi`, etc.) is pinned in that file, so running the hooks
|
||||
locally uses exactly the same versions as CI. A few `local` hooks — most notably
|
||||
`clang-tidy` and `cargo fmt` — run tools from your own environment; see
|
||||
[Installing clang-tidy](#installing-clang-tidy) and
|
||||
[Rust](./docs/build/environment.md#rust) for how to get those.
|
||||
`clang-tidy` — run tools from your own environment; see
|
||||
[Installing clang-tidy](#installing-clang-tidy) for how to get those.
|
||||
|
||||
To get started, install `pre-commit` and enable the git hook scripts:
|
||||
|
||||
@@ -256,7 +255,6 @@ The hooks configured in this repository include, among others:
|
||||
- `clang-tidy` — C++ static analysis (see [Clang-tidy](#clang-tidy)); opt in with `TIDY=1`
|
||||
- `fix-include-style`, `fix-pragma-once`, `check-doxygen-style` — C++ hygiene
|
||||
- `gersemi` — CMake formatting
|
||||
- `cargo fmt` — Rust formatting for the crates in `crates/`
|
||||
- `prettier`, `black`, `shfmt` — formatting for JavaScript/JSON/Markdown, Python, and shell
|
||||
- `cspell` — spell checking
|
||||
|
||||
@@ -321,11 +319,7 @@ See the [environment setup guide](./docs/build/environment.md#clang-tidy) for ho
|
||||
|
||||
### Running clang-tidy locally
|
||||
|
||||
Before running clang-tidy, you must generate the files it depends on (protobuf headers, and, when the project is configured with `-Drust=ON`, the cxxbridge headers from the Rust crates). Configure the project as described in [`BUILD.md`](./BUILD.md), then build the `tidy_prerequisites` target, which generates all of them:
|
||||
|
||||
```bash
|
||||
cmake --build build --target tidy_prerequisites
|
||||
```
|
||||
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.
|
||||
|
||||
#### Via pre-commit (recommended)
|
||||
|
||||
|
||||
@@ -54,7 +54,6 @@ Here are some good places to start learning the source code:
|
||||
| `./docs` | Source documentation files and doxygen config. |
|
||||
| `./cfg` | Example configuration files. |
|
||||
| `./src` | Source code. |
|
||||
| `./crates` | Rust source code. |
|
||||
|
||||
Some of the directories under `src` are external repositories included using
|
||||
git-subtree. See those directories' README files for more details.
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Fail if a binary under <path> records a /nix/store path it resolves at run
|
||||
# time. See docs/build/nix.md#prebuilt-packages for why that matters.
|
||||
#
|
||||
# <path> is a file or a directory. macOS: nothing may reference the store, so
|
||||
# point it at whole trees. Linux: the toolchain always writes the store into
|
||||
# PT_INTERP and RUNPATH, so only at what cmake/PatchNixBinary.cmake retargets.
|
||||
#
|
||||
# Only Mach-O / ELF is inspected. Static archives hold store paths in debug info
|
||||
# alone; the scripts in a Conan cache are all git hook samples and autotools
|
||||
# scratch, 36 false positives to 0 real.
|
||||
#
|
||||
# Usage: bin/check-nix-store-refs.sh <path>
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
if [ "$#" -ne 1 ]; then
|
||||
echo "usage: $0 <path>" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [ ! -e "$1" ]; then
|
||||
echo "$0: no such path: $1" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
case "$(uname -s)" in
|
||||
Darwin)
|
||||
format=Mach-O
|
||||
recorded_paths=macho_recorded_paths
|
||||
tool=otool
|
||||
;;
|
||||
Linux)
|
||||
format=ELF
|
||||
recorded_paths=elf_recorded_paths
|
||||
tool=readelf
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported OS - skipping the Nix store reference check."
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
# `pipefail` would catch this too, but only as a bare nonzero exit.
|
||||
if ! command -v "${tool}" >/dev/null; then
|
||||
echo "$0: ${tool} not found; cannot inspect binaries" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Both list what the file records. `ldd` would answer what this machine resolves
|
||||
# now, which is wrong both ways: store paths for a correctly patched binary,
|
||||
# silence for a store RUNPATH that resolves nowhere.
|
||||
|
||||
# `name` covers LC_ID_DYLIB and LC_LOAD*_DYLIB, `path` covers LC_RPATH.
|
||||
macho_recorded_paths() {
|
||||
otool -l "$1" | sed -nE 's#^ *(name|path) ([^ ]*).*#\2#p'
|
||||
}
|
||||
|
||||
# RPATH and RUNPATH are colon-separated.
|
||||
elf_recorded_paths() {
|
||||
readelf -ldW "$1" |
|
||||
sed -nE \
|
||||
-e 's#.*program interpreter: ([^]]*)\].*#\1#p' \
|
||||
-e 's#.*\((RPATH|RUNPATH|NEEDED)\).*\[([^]]*)\].*#\2#p' |
|
||||
tr ':' '\n'
|
||||
}
|
||||
|
||||
checked=0
|
||||
skipped=0
|
||||
leaked=0
|
||||
|
||||
while IFS= read -r file; do
|
||||
case "$(file -b "${file}" 2>/dev/null)" in
|
||||
*"${format}"*) ;;
|
||||
*)
|
||||
skipped=$((skipped + 1))
|
||||
continue
|
||||
;;
|
||||
esac
|
||||
checked=$((checked + 1))
|
||||
|
||||
# Filter after extracting, or a search path starting elsewhere ($ORIGIN)
|
||||
# hides the rest. `sed` not `grep`: grep calls "no matches" a failure, and
|
||||
# the `|| true` that would need masks a broken pipeline too.
|
||||
refs="$("${recorded_paths}" "${file}" | sed -n '\#^/nix/store/#p' | sort -u)"
|
||||
if [ -n "${refs}" ]; then
|
||||
leaked=$((leaked + 1))
|
||||
echo "::error file=${file}::references the Nix store at run time"
|
||||
echo "${file}"
|
||||
echo "${refs}" | sed 's/^/ /'
|
||||
fi
|
||||
done < <(find "$1" -type f \( -perm -u+x -o -name '*.dylib' -o -name '*.so*' \))
|
||||
|
||||
echo "$1: checked ${checked}, skipped ${skipped}, ${leaked} with Nix store references."
|
||||
|
||||
if [ "${leaked}" -ne 0 ]; then
|
||||
cat >&2 <<'EOF'
|
||||
|
||||
Fixes, in order of preference:
|
||||
- A Conan package built before this check existed: drop it
|
||||
(`conan remove '<name>/*'`) and rebuild.
|
||||
- A binary that should have been retargeted to the system loader: check that
|
||||
cmake/PatchNixBinary.cmake ran for it.
|
||||
- Link the macOS system library instead of the Nix one - see
|
||||
libresolvSystemStub in nix/darwin.nix.
|
||||
- No system library exists (libstdc++): link it statically.
|
||||
- None of the above: pin the toolchain into the package ID, following
|
||||
`user.package:libc_version` in conan/profiles/ci.
|
||||
EOF
|
||||
exit 1
|
||||
fi
|
||||
@@ -15,14 +15,10 @@
|
||||
# - Windows: the core build tools only (CMake, Conan, Git, Python).
|
||||
# MSVC is expected to be provided separately and is not checked here.
|
||||
#
|
||||
# Some tools (clang-format, clang-tidy, doxygen, gcovr, gh, git-cliff, gpg,
|
||||
# pre-commit, run-clang-tidy) are present in our Linux CI images and in local
|
||||
# development setups, but not in the macOS CI environment. They are checked
|
||||
# everywhere except when running in CI on macOS.
|
||||
#
|
||||
# Tools that Nix also exposes under a version-suffixed name (`clang-tidy-22`,
|
||||
# `g++-15`, ...) are probed under both names: a suffixed name can break while
|
||||
# the plain one still works (see mkVersionedToolLinks in nix/packages.nix).
|
||||
# Some tools (clang-format, doxygen, gcovr, gh, git-cliff, gpg, pre-commit,
|
||||
# run-clang-tidy) are present in our Linux CI images and in local development
|
||||
# setups, but not in the macOS CI environment. They are checked everywhere
|
||||
# except when running in CI on macOS.
|
||||
#
|
||||
# Environment variables:
|
||||
# CI if set, skip the tools above when on macOS.
|
||||
@@ -30,27 +26,14 @@
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
# Version suffixes of the Nix tool links, tracking nix/packages.nix.
|
||||
gcc_version=15
|
||||
llvm_version=22
|
||||
|
||||
missing=()
|
||||
checked=0
|
||||
|
||||
# tool_path <name>
|
||||
# Fully resolved path of a tool, so the snapshots record which derivation
|
||||
# provides it. Prints nothing when it isn't on PATH.
|
||||
tool_path() {
|
||||
local path
|
||||
path="$(command -v "$1" 2>/dev/null)" || return 0
|
||||
readlink -f "${path}" 2>/dev/null || printf '%s' "${path}"
|
||||
}
|
||||
|
||||
# check <name> [probe-command...]
|
||||
# Runs the probe (default: "<name> --version"), capturing both stdout and
|
||||
# stderr, and prints three lines: the status and name, the first non-blank line
|
||||
# of the probe output (its version, or the error when it failed), and the tool's
|
||||
# resolved path. Records <name> as missing if it is not found or exits non-zero.
|
||||
# stderr, and prints one aligned line: the status, the name, and the first
|
||||
# non-blank line of the probe output (its version). Records <name> as missing
|
||||
# if the command is not found or exits non-zero.
|
||||
check() {
|
||||
local name="$1"
|
||||
shift
|
||||
@@ -60,17 +43,14 @@ check() {
|
||||
fi
|
||||
|
||||
checked=$((checked + 1))
|
||||
local output version path
|
||||
path="$(tool_path "${name}")"
|
||||
local output version
|
||||
if output="$("${probe[@]}" 2>&1)"; then
|
||||
printf ' ✅ %s\n' "${name}"
|
||||
version="$(printf '%s\n' "${output}" | grep -m1 '[^[:space:]]' || true)"
|
||||
printf ' [ ok ] %-20s %s\n' "${name}" "${version}"
|
||||
else
|
||||
printf ' ❌ %s\n' "${name}"
|
||||
printf ' [MISS] %s\n' "${name}"
|
||||
missing+=("${name}")
|
||||
fi
|
||||
version="$(printf '%s\n' "${output}" | grep -m1 '[^[:space:]]' || true)"
|
||||
printf ' %s\n' "${version:-(no output)}"
|
||||
printf ' %s\n' "${path:-(not found)}"
|
||||
}
|
||||
|
||||
case "$(uname -s)" in
|
||||
@@ -102,9 +82,7 @@ if [ "${os}" = "linux" ] || [ "${os}" = "macos" ]; then
|
||||
echo "Development tooling:"
|
||||
check ccache
|
||||
check clang
|
||||
check "clang-${llvm_version}"
|
||||
check clang++
|
||||
check "clang++-${llvm_version}"
|
||||
check ClangBuildAnalyzer
|
||||
check curl
|
||||
check file
|
||||
@@ -123,14 +101,7 @@ if [ "${os}" = "linux" ] || [ "${os}" = "macos" ]; then
|
||||
# setups, but not in the macOS CI environment. So check them everywhere
|
||||
# except when running in CI on macOS.
|
||||
if [ "${os}" = "linux" ] || [ -z "${CI:-}" ]; then
|
||||
check clang-apply-replacements
|
||||
check "clang-apply-replacements-${llvm_version}"
|
||||
check clang-format
|
||||
check "clang-format-${llvm_version}"
|
||||
# clang-tidy leads --version with the LLVM banner, not the version.
|
||||
tidy_probe="--version | grep -m1 -oE 'LLVM version [0-9.]+'"
|
||||
check clang-tidy sh -c "clang-tidy ${tidy_probe}"
|
||||
check "clang-tidy-${llvm_version}" sh -c "clang-tidy-${llvm_version} ${tidy_probe}"
|
||||
check dot
|
||||
check doxygen
|
||||
check gcovr
|
||||
@@ -141,7 +112,6 @@ if [ "${os}" = "linux" ] || [ "${os}" = "macos" ]; then
|
||||
# pre-commit, or its alternative implementation prek
|
||||
check pre-commit sh -c 'pre-commit --version || prek --version'
|
||||
check run-clang-tidy run-clang-tidy --help
|
||||
check "run-clang-tidy-${llvm_version}" "run-clang-tidy-${llvm_version}" --help
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -156,7 +126,7 @@ if [ "${os}" = "linux" ] || [ "${os}" = "macos" ]; then
|
||||
check cargo-audit cargo audit --version
|
||||
check cargo-llvm-cov cargo llvm-cov --version
|
||||
check cargo-nextest cargo nextest --version
|
||||
check clippy-driver
|
||||
check clippy clippy-driver --version
|
||||
check rust-analyzer
|
||||
check rustc
|
||||
check rustfmt
|
||||
@@ -168,11 +138,7 @@ if [ "${os}" = "linux" ]; then
|
||||
echo
|
||||
echo "GCC toolchain:"
|
||||
check gcc
|
||||
check "gcc-${gcc_version}"
|
||||
check g++
|
||||
check "g++-${gcc_version}"
|
||||
check cpp
|
||||
check "cpp-${gcc_version}"
|
||||
check gcov
|
||||
|
||||
echo
|
||||
@@ -197,9 +163,9 @@ else
|
||||
checked=$((checked + 1))
|
||||
tmp_clone="$(mktemp -d)"
|
||||
if git clone --depth 1 https://github.com/XRPLF/actions.git "${tmp_clone}/actions" >/dev/null 2>&1; then
|
||||
printf ' ✅ git clone over HTTPS\n'
|
||||
printf ' [ ok ] git clone over HTTPS\n'
|
||||
else
|
||||
printf ' ❌ git clone over HTTPS\n'
|
||||
printf ' [MISS] git clone over HTTPS\n'
|
||||
missing+=("git-https-clone")
|
||||
fi
|
||||
rm -rf "${tmp_clone}"
|
||||
@@ -207,9 +173,9 @@ fi
|
||||
|
||||
echo
|
||||
if [ "${#missing[@]}" -eq 0 ]; then
|
||||
echo "✅ All ${checked} checked tools are present and runnable."
|
||||
echo "All ${checked} checked tools are present and runnable."
|
||||
else
|
||||
echo "❌ Missing or non-functional tools (${#missing[@]} of ${checked}):" >&2
|
||||
echo "Missing or non-functional tools (${#missing[@]} of ${checked}):" >&2
|
||||
for tool in "${missing[@]}"; do
|
||||
echo " - ${tool}" >&2
|
||||
done
|
||||
|
||||
@@ -120,10 +120,7 @@ if(MSVC)
|
||||
_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS
|
||||
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:Debug>>:_CRTDBG_MAP_ALLOC>
|
||||
)
|
||||
target_link_libraries(
|
||||
common
|
||||
INTERFACE -errorreport:none -machine:X64 -ignore:4099
|
||||
)
|
||||
target_link_libraries(common INTERFACE -errorreport:none -machine:X64)
|
||||
else()
|
||||
target_compile_options(
|
||||
common
|
||||
|
||||
@@ -51,8 +51,6 @@ target_compile_options(
|
||||
|
||||
target_link_libraries(xrpl.libpb PUBLIC protobuf::libprotobuf gRPC::grpc++)
|
||||
|
||||
add_dependencies(tidy_prerequisites xrpl.libpb)
|
||||
|
||||
# TODO: Clean up the number of library targets later.
|
||||
add_library(xrpl.imports.main INTERFACE)
|
||||
|
||||
@@ -69,7 +67,6 @@ target_link_libraries(
|
||||
Xrpl::opts
|
||||
Xrpl::syslibs
|
||||
secp256k1::secp256k1
|
||||
wasmi::wasmi
|
||||
xrpl.libpb
|
||||
xxHash::xxhash
|
||||
$<$<BOOL:${voidstar}>:antithesis-sdk-cpp>
|
||||
|
||||
@@ -32,11 +32,6 @@ endif()
|
||||
|
||||
option(benchmark "Build benchmarks" ON)
|
||||
|
||||
# When OFF, the crates directory is not added to the build at all: no Rust
|
||||
# toolchain is required, no cxxbridge bindings are generated, and the C++ tests
|
||||
# that consume those bindings are left out of the build tree.
|
||||
option(rust "Build the Rust crates and the C++ code that depends on them" OFF)
|
||||
|
||||
# Enabled by default so every header is compiled on its own as the main file of
|
||||
# its own compile_commands.json entry - this is what lets clang-tidy (and clangd
|
||||
# and IDEs) analyse a header's own includes directly. The per-header objects are
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
"requires": [
|
||||
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1782392402.122708",
|
||||
"xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1782392402.420688",
|
||||
"wasmi/1.0.9#1fecdab9b90c96698eb35ea99ca4f5cb%1782307153.343419",
|
||||
"sqlite3/3.53.0#324ada52333108388a9a6108bfa96734%1782392403.185447",
|
||||
"soci/4.0.3#e726491a03468795453f7c83fc924a96%1782392402.679521",
|
||||
"snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1782307151.633168",
|
||||
@@ -24,7 +23,6 @@
|
||||
"fast_float/8.2.10#f6f28d6bb22112078e7dbda611caf681%1782494504.298",
|
||||
"ed25519/2015.03#ae761bdc52730a843f0809bdf6c1b1f6%1782307148.15562",
|
||||
"date/3.0.4#862e11e80030356b53c2c38599ceb32b%1782392402.538492",
|
||||
"corrosion/0.6.1#bfa292df0a957bc70a450ff316cd9435%1786119416.131296",
|
||||
"c-ares/1.34.6#545240bb1c40e2cacd4362d6b8967650%1782392402.681654",
|
||||
"bzip2/1.0.8#c470882369c2d95c5c77e970c0c7e321%1782392402.296732",
|
||||
"boost/1.91.0#ea540ca2133d831b560036aa24dece3c%1782392419.475605",
|
||||
|
||||
@@ -28,7 +28,6 @@ class Xrpl(ConanFile):
|
||||
}
|
||||
|
||||
requires = [
|
||||
"corrosion/0.6.1",
|
||||
"ed25519/2015.03",
|
||||
"fast_float/8.2.10",
|
||||
"grpc/1.81.1",
|
||||
@@ -36,7 +35,6 @@ class Xrpl(ConanFile):
|
||||
"nudb/2.0.9",
|
||||
"openssl/3.6.3",
|
||||
"soci/4.0.3",
|
||||
"wasmi/1.0.9",
|
||||
"zlib/1.3.2",
|
||||
]
|
||||
|
||||
@@ -225,7 +223,6 @@ class Xrpl(ConanFile):
|
||||
"soci::soci",
|
||||
"secp256k1::secp256k1",
|
||||
"sqlite3::sqlite",
|
||||
"wasmi::wasmi",
|
||||
"xxhash::xxhash",
|
||||
"zlib::zlib",
|
||||
]
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
# The Rust static libraries are linked into C++ targets, so the runtime linkage
|
||||
# here has to match what the C++ build uses (see cmake/XrplCompiler.cmake).
|
||||
#
|
||||
# macOS needs nothing: AppleClang cannot link libgcc/libc++ statically, so the
|
||||
# C++ build skips those flags on Apple as well.
|
||||
|
||||
# Both amd64 and arm64 Linux builds link libgcc statically. This only affects
|
||||
# links that rustc itself drives (`cargo test` binaries and the like) — the
|
||||
# `staticlib` crates consumed by CMake are archived, not linked, so rustc
|
||||
# silently ignores link args for them. Keeping libgcc_s.so.1 off the xrpld link
|
||||
# line is handled in crates/CMakeLists.txt instead.
|
||||
[target.'cfg(target_os = "linux")']
|
||||
rustflags = ["-C", "link-args=-static-libgcc"]
|
||||
|
||||
# Windows builds use the static MSVC runtime.
|
||||
[target.'cfg(windows)']
|
||||
rustflags = ["-C", "target-feature=+crt-static"]
|
||||
@@ -1,104 +0,0 @@
|
||||
find_package(Corrosion REQUIRED)
|
||||
|
||||
corrosion_import_crate(MANIFEST_PATH ${CMAKE_CURRENT_SOURCE_DIR}/Cargo.toml)
|
||||
|
||||
# The generated C++ lands in the build tree, so put a .clang-tidy next to it to
|
||||
# keep clang-tidy from analyzing code we don't own.
|
||||
configure_file(
|
||||
generated.clang-tidy
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/.clang-tidy"
|
||||
COPYONLY
|
||||
)
|
||||
|
||||
add_custom_target(xrpl_crates)
|
||||
add_dependencies(tidy_prerequisites xrpl_crates)
|
||||
|
||||
# On macOS, ld warns `ignoring duplicate libraries` when linking a crate.
|
||||
# Corrosion is the source of both duplicates it names:
|
||||
#
|
||||
# * The crate archive and its cxxbridge archive, because
|
||||
# `corrosion_add_cxxbridge` makes the two depend on each other, and CMake
|
||||
# repeats a static library cycle on the link line so single-pass linkers can
|
||||
# resolve it. (LINK_INTERFACE_MULTIPLICITY can only raise that count.)
|
||||
# * `-lSystem`, which Corrosion copies from rustc's `native-static-libs` even
|
||||
# though the compiler driver always links libSystem.
|
||||
#
|
||||
# ld needs neither: it resolves the cycle from one copy of each archive and
|
||||
# links libSystem once. So silence the warning rather than rewrite Corrosion's
|
||||
# link interface, which the cycle is also part of. The option itself is old —
|
||||
# Xcode 15 is only where the warning became the default — and the check below
|
||||
# leaves it out on a linker that does not know it.
|
||||
if(is_macos)
|
||||
include(CheckLinkerFlag)
|
||||
check_linker_flag(
|
||||
CXX
|
||||
-Wl,-no_warn_duplicate_libraries
|
||||
have_no_warn_duplicate_libraries
|
||||
)
|
||||
endif()
|
||||
|
||||
function(_unlink_libgcc_s crate)
|
||||
if(NOT (is_linux AND static))
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Corrosion exposes a crate's staticlib as an imported `<crate>-static`
|
||||
# target and puts the native libs in its INTERFACE_LINK_LIBRARIES. If either
|
||||
# of those changes, warn instead of silently letting libgcc_s.so.1 return.
|
||||
set(imported "${crate}-static")
|
||||
if(NOT TARGET ${imported})
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"Corrosion did not create the imported target '${imported}', so "
|
||||
"libgcc_s cannot be removed from the link interface of '${crate}'. "
|
||||
"xrpld will link libgcc_s.so.1 dynamically. Check where Corrosion "
|
||||
"${CORROSION_VERSION} now records `native-static-libs`."
|
||||
)
|
||||
return()
|
||||
endif()
|
||||
|
||||
get_target_property(libs ${imported} INTERFACE_LINK_LIBRARIES)
|
||||
if(NOT "gcc_s" IN_LIST libs)
|
||||
message(
|
||||
WARNING
|
||||
"'gcc_s' was not in the link interface of '${imported}' as "
|
||||
"expected. If the Rust toolchain stopped reporting it this "
|
||||
"workaround is obsolete and can be deleted; otherwise xrpld may "
|
||||
"link libgcc_s.so.1 dynamically. Verify with: "
|
||||
"objdump -p xrpld | grep NEEDED"
|
||||
)
|
||||
return()
|
||||
endif()
|
||||
|
||||
list(REMOVE_ITEM libs gcc_s)
|
||||
set_property(TARGET ${imported} PROPERTY INTERFACE_LINK_LIBRARIES ${libs})
|
||||
endfunction()
|
||||
|
||||
function(add_xrpl_crate name)
|
||||
cmake_parse_arguments(ARG "" "CRATE" "FILES" ${ARGN})
|
||||
_unlink_libgcc_s(${ARG_CRATE})
|
||||
# `cc` picks its runtime flag from `crt-static` alone, so it compiles a
|
||||
# crate's C++ with `-MT`; Debug needs `-MTd` (to match cmake/XrplCompiler.cmake).
|
||||
if(is_msvc)
|
||||
corrosion_set_env_vars(
|
||||
${ARG_CRATE}
|
||||
"$<$<CONFIG:Debug>:CXXFLAGS=-MTd>"
|
||||
)
|
||||
endif()
|
||||
corrosion_add_cxxbridge(${name}_cxxbridge CRATE ${ARG_CRATE} FILES
|
||||
${ARG_FILES}
|
||||
)
|
||||
# Generated cxxbridge headers don't exist at configure time; CMake 3.28+
|
||||
# validates INTERFACE_SOURCES on consuming targets. Clear it to skip the
|
||||
# existence check — build-time ordering is enforced by the custom commands.
|
||||
set_target_properties(${name}_cxxbridge PROPERTIES INTERFACE_SOURCES "")
|
||||
if(have_no_warn_duplicate_libraries)
|
||||
target_link_options(
|
||||
${name}_cxxbridge
|
||||
INTERFACE -Wl,-no_warn_duplicate_libraries
|
||||
)
|
||||
endif()
|
||||
add_dependencies(xrpl_crates ${name}_cxxbridge)
|
||||
endfunction()
|
||||
|
||||
add_xrpl_crate(rs_hello_world CRATE rs_hello_world FILES lib.rs)
|
||||
301
crates/Cargo.lock
generated
301
crates/Cargo.lock
generated
@@ -1,301 +0,0 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.61"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
"strsim",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9"
|
||||
|
||||
[[package]]
|
||||
name = "codespan-reporting"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af491d569909a7e4dee0ad7db7f5341fef5c614d5b8ec8cf765732aba3cff681"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"termcolor",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxx"
|
||||
version = "1.0.199"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "824894a4a85dca76d4c95c2b9098c036f5a29f627b30c12780774f6654e60974"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cxx-build",
|
||||
"cxxbridge-cmd",
|
||||
"cxxbridge-flags",
|
||||
"cxxbridge-macro",
|
||||
"foldhash",
|
||||
"link-cplusplus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxx-build"
|
||||
version = "1.0.199"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1ae0b651ea5b0000b19513aef5a03f194d7e3486f2d9258b658da8677fe9036"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"codespan-reporting",
|
||||
"indexmap",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"scratch",
|
||||
"syn 3.0.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-cmd"
|
||||
version = "1.0.199"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb05f91d3fb8435d9bab6ac5ce6ac1868be774325fb7fb2a91be39393b21388e"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"codespan-reporting",
|
||||
"indexmap",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 3.0.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-flags"
|
||||
version = "1.0.199"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf293202e0e3e98495785745389e8d0755b217e66f19194a5c695c25e03282ef"
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-macro"
|
||||
version = "1.0.199"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca001d746947c7249ed9d332a10f7a59daedbafeb0ec68c5c18a7db7a93f6ccc"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 3.0.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
||||
|
||||
[[package]]
|
||||
name = "foldhash"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "link-cplusplus"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f78c730aaa7d0b9336a299029ea49f9ee53b0ed06e9202e8cb7db9bae7b8c82"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rs-hello_world"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cxx",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scratch"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d68f2ec51b097e4c1a75b681a8bec621909b5e91f15bb7b840c4f2f7b01148b2"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_core"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.117"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "3.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.61.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
@@ -1,15 +0,0 @@
|
||||
[workspace]
|
||||
members = ["hello_world"]
|
||||
resolver = "3"
|
||||
|
||||
[workspace.dependencies]
|
||||
cxx = { version = "1.0.198", features = ["c++20"] }
|
||||
|
||||
[workspace.package]
|
||||
edition = "2024"
|
||||
|
||||
[profile.release]
|
||||
opt-level = 3
|
||||
overflow-checks = true
|
||||
lto = true
|
||||
debug = true
|
||||
@@ -1,10 +0,0 @@
|
||||
---
|
||||
# Neutralizes clang-tidy for the corrosion/cxxbridge-generated C++. Copied into
|
||||
# the crates build directory by crates/CMakeLists.txt, next to the generated
|
||||
# sources, so clang-tidy picks it up instead of the top-level configuration.
|
||||
#
|
||||
# One check is kept enabled to avoid clang-tidy's "no checks enabled" error.
|
||||
Checks: "-*,google-readability-todo"
|
||||
WarningsAsErrors: ""
|
||||
HeaderFilterRegex: ""
|
||||
InheritParentConfig: false
|
||||
@@ -1,10 +0,0 @@
|
||||
[package]
|
||||
name = "rs-hello_world"
|
||||
version = "0.1.0"
|
||||
edition.workspace = true
|
||||
|
||||
[lib]
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
[dependencies]
|
||||
cxx.workspace = true
|
||||
@@ -1,10 +0,0 @@
|
||||
#[cxx::bridge(namespace = "rs::hello_world")]
|
||||
mod ffi {
|
||||
extern "Rust" {
|
||||
fn hello_world() -> String;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn hello_world() -> String {
|
||||
"hello_world".to_string()
|
||||
}
|
||||
22
docs/build/environment.md
vendored
22
docs/build/environment.md
vendored
@@ -46,9 +46,6 @@ Besides a compiler, building `xrpld` requires:
|
||||
On Linux and macOS, the [Nix development shell](./nix.md) provides all of them
|
||||
(see below). On Windows they have to be installed manually.
|
||||
|
||||
Building with `-Drust=ON` additionally requires a Rust toolchain, see
|
||||
[Rust](#rust). A default build does not, so it is not in the table above.
|
||||
|
||||
Once they are in place, verify that everything is installed and runnable with:
|
||||
|
||||
```bash
|
||||
@@ -124,25 +121,6 @@ manually:
|
||||
- [Git for Windows](https://git-scm.com/download/win)
|
||||
- Python, Conan, and CMake, at the versions listed in
|
||||
[Required tools](#required-tools).
|
||||
- a [Rust toolchain](https://rustup.rs) — only needed to build with
|
||||
`-Drust=ON`, see [Rust](#rust)
|
||||
|
||||
## Rust
|
||||
|
||||
The repository contains a Rust workspace in [`crates/`](../../crates), whose
|
||||
crates are exposed to C++ through [cxx](https://cxx.rs) bindings. It is **not**
|
||||
part of a default build: the CMake `rust` option is OFF by default, and with it
|
||||
off no Rust toolchain is needed. It is only required when configuring with
|
||||
`-Drust=ON` (which is what CI does), see [Options](../../BUILD.md#options).
|
||||
|
||||
The toolchain (`cargo`, `rustc`) is pinned to the channel in
|
||||
[`rust-toolchain.toml`](../../rust-toolchain.toml) at the repository root. If
|
||||
you install Rust with [rustup](https://rustup.rs), that file is picked up
|
||||
automatically, and `cargo`/`rustc` in the repository will use the pinned
|
||||
version.
|
||||
|
||||
Everything else the Rust build needs on the CMake side comes from Conan along
|
||||
with the rest of the dependencies, so there is nothing further to install.
|
||||
|
||||
## Clang-tidy
|
||||
|
||||
|
||||
21
docs/install-legacy.md → docs/build/install.md
vendored
21
docs/install-legacy.md → docs/build/install.md
vendored
@@ -1,10 +1,3 @@
|
||||
# Installing xrpld 3.3.0 and earlier
|
||||
|
||||
> [!IMPORTANT]
|
||||
> These instructions apply to xrpld 3.3.0 and earlier, published to
|
||||
> repos.ripple.com.
|
||||
> For later releases see [install.md](./install.md).
|
||||
|
||||
This document contains instructions for installing xrpld.
|
||||
The APT package manager is common on Debian-based Linux distributions like
|
||||
Ubuntu,
|
||||
@@ -59,7 +52,7 @@ The default [prefix][1] is typically `/usr/local` on Linux and macOS and
|
||||
|
||||
5. Add the appropriate XRPL repository for your operating system version:
|
||||
|
||||
echo "deb [signed-by=/usr/local/share/keyrings/ripple-key.gpg] https://repos.ripple.com/repos/rippled-deb focal stable" | \
|
||||
echo "deb [signed-by=/usr/local/share/keyrings/ripple-key.gpg] https://repos.ripple.com/repos/xrpld-deb focal stable" | \
|
||||
sudo tee -a /etc/apt/sources.list.d/ripple.list
|
||||
|
||||
The above example is appropriate for **Ubuntu 20.04 Focal Fossa**. For other operating systems, replace the word `focal` with one of the following:
|
||||
@@ -113,8 +106,8 @@ The default [prefix][1] is typically `/usr/local` on Linux and macOS and
|
||||
enabled=1
|
||||
gpgcheck=0
|
||||
repo_gpgcheck=1
|
||||
baseurl=https://repos.ripple.com/repos/rippled-rpm/stable/
|
||||
gpgkey=https://repos.ripple.com/repos/rippled-rpm/stable/repodata/repomd.xml.key
|
||||
baseurl=https://repos.ripple.com/repos/xrpld-rpm/stable/
|
||||
gpgkey=https://repos.ripple.com/repos/xrpld-rpm/stable/repodata/repomd.xml.key
|
||||
REPOFILE
|
||||
|
||||
_Unstable_
|
||||
@@ -125,8 +118,8 @@ The default [prefix][1] is typically `/usr/local` on Linux and macOS and
|
||||
enabled=1
|
||||
gpgcheck=0
|
||||
repo_gpgcheck=1
|
||||
baseurl=https://repos.ripple.com/repos/rippled-rpm/unstable/
|
||||
gpgkey=https://repos.ripple.com/repos/rippled-rpm/unstable/repodata/repomd.xml.key
|
||||
baseurl=https://repos.ripple.com/repos/xrpld-rpm/unstable/
|
||||
gpgkey=https://repos.ripple.com/repos/xrpld-rpm/unstable/repodata/repomd.xml.key
|
||||
REPOFILE
|
||||
|
||||
_Nightly_
|
||||
@@ -137,8 +130,8 @@ The default [prefix][1] is typically `/usr/local` on Linux and macOS and
|
||||
enabled=1
|
||||
gpgcheck=0
|
||||
repo_gpgcheck=1
|
||||
baseurl=https://repos.ripple.com/repos/rippled-rpm/nightly/
|
||||
gpgkey=https://repos.ripple.com/repos/rippled-rpm/nightly/repodata/repomd.xml.key
|
||||
baseurl=https://repos.ripple.com/repos/xrpld-rpm/nightly/
|
||||
gpgkey=https://repos.ripple.com/repos/xrpld-rpm/nightly/repodata/repomd.xml.key
|
||||
REPOFILE
|
||||
|
||||
2. Fetch the latest repo updates:
|
||||
84
docs/build/nix.md
vendored
84
docs/build/nix.md
vendored
@@ -7,7 +7,7 @@ This guide explains how to use Nix to set up a reproducible development environm
|
||||
## Benefits of Using Nix
|
||||
|
||||
- **Reproducible environment**: Everyone gets the same versions of tools and compilers
|
||||
- **Matches CI**: The Linux CI runs in Docker images built from this exact Nix environment, and CI builds some macOS configurations in it as well
|
||||
- **Matches CI**: The Linux CI runs in Docker images built from this exact Nix environment
|
||||
- **No system pollution**: Dependencies are isolated and don't affect your system packages
|
||||
- **Consistent compilers**: The GCC and Clang shells use the same versions as CI
|
||||
- **Quick setup**: Get started with a single command
|
||||
@@ -68,7 +68,7 @@ A compiler can be chosen by providing its name with the `.#` prefix, e.g. `nix d
|
||||
|
||||
On Linux, `.#gcc` and `.#clang` provide the exact toolchain CI uses:
|
||||
the compiler (pinned in [`nix/packages.nix`](../../nix/packages.nix))
|
||||
rebuilt against the pinned custom glibc (see [`nix/linux.nix`](../../nix/linux.nix)).
|
||||
rebuilt against the pinned custom glibc (see [`nix/compilers.nix`](../../nix/compilers.nix)).
|
||||
Building that toolchain the first time is slow unless it is fetched from a Nix binary cache.
|
||||
If you don't need the custom glibc, the Linux-only `.#gcc-plain` and `.#clang-plain`
|
||||
give you the stock nixpkgs compilers of the same versions.
|
||||
@@ -128,12 +128,6 @@ Coverage builds (`-Dcoverage=ON`) work in the `gcc` shell (and `gcc-plain` on Li
|
||||
each ships a `gcov` matching its compiler, since Nix's cc-wrapper does not expose one.
|
||||
The `clang` shells do not include `llvm-cov`, so use a `gcc` shell for coverage.
|
||||
|
||||
Builds of the Rust crates (`-Drust=ON`) also work out of the box: every shell
|
||||
provides the Rust toolchain pinned in
|
||||
[`rust-toolchain.toml`](../../rust-toolchain.toml) (see
|
||||
[Rust](./environment.md#rust)), plus the `cargo-audit`, `cargo-llvm-cov` and
|
||||
`cargo-nextest` plugins.
|
||||
|
||||
## Conan configuration
|
||||
|
||||
The shell runs [`conan/init.sh`](../../conan/init.sh) on entry, so
|
||||
@@ -148,80 +142,14 @@ environment — CI runs in Docker images that bundle the dev shell's toolchain (
|
||||
`-plain` shells do not match that toolchain's glibc, so binaries from the remote
|
||||
are not a reliable match there.
|
||||
|
||||
On **macOS**, CI also builds in this Nix environment, in Debug and Release (the
|
||||
`macos-arm64-*-nix` configurations — Debug because the profile defaults to it).
|
||||
The Nix build resolves to `compiler=clang`, so it gets its own package IDs,
|
||||
separate from the Apple Clang ones. The
|
||||
[dependency upload](../../.github/workflows/upload-conan-deps.yml) publishes them
|
||||
on pushes to `develop` and on manual runs — its nightly run rebuilds everything
|
||||
from source but uploads nothing — so once a set has been published `nix develop`
|
||||
can reuse it instead of compiling every dependency locally. These configurations
|
||||
run outside the reduced pull-request matrix, so label a PR `Full CI build` when it
|
||||
touches `flake.lock` or `nix/`.
|
||||
On **macOS**, CI builds with Apple Clang, so the remote holds nothing for the Nix
|
||||
`clang` toolchain and dependencies are compiled locally. We do not publish
|
||||
Nix-built macOS binaries because a Conan package ID records the compiler version
|
||||
but not the nixpkgs revision.
|
||||
|
||||
To compile everything from source, add `--build '*'` to the `conan install`
|
||||
command.
|
||||
|
||||
### Why the nixpkgs revision is not part of the package ID
|
||||
|
||||
A Conan package ID records the compiler and its major version, but nothing about
|
||||
the nixpkgs revision the toolchain came from — and `flake.lock` moves far more
|
||||
often than the toolchain meaningfully changes, so folding it in would rebuild
|
||||
every dependency on every bump for nothing.
|
||||
|
||||
That is safe as long as no cached artifact resolves a `/nix/store` path at run
|
||||
time, because store paths change on every update and the old ones disappear with
|
||||
`nix-collect-garbage`. With the `clang` toolchain macOS CI and the dev shell use,
|
||||
they do not: it links against `/usr/lib/libc++` and `/usr/lib/libSystem`, and
|
||||
store paths reach the `.a` files only through debug info, which nothing resolves
|
||||
at link or run time.
|
||||
|
||||
> [!WARNING]
|
||||
> This does not hold for `nix develop .#gcc` on macOS. There is no system
|
||||
> libstdc++, so GCC links its own from the store and every binary keeps a
|
||||
> `/nix/store` reference. That shell is fine for tooling, but it is not a build
|
||||
> configuration CI covers, and no dependency binaries are published for it.
|
||||
|
||||
This is checked rather than assumed.
|
||||
[`bin/check-nix-store-refs.sh`](../../bin/check-nix-store-refs.sh) takes one file
|
||||
or directory and fails if a binary under it resolves a store path at run time.
|
||||
CI runs it over the build output and the Conan cache, and again in the upload job
|
||||
before anything is published. You can run it yourself:
|
||||
|
||||
```bash
|
||||
bin/check-nix-store-refs.sh build
|
||||
bin/check-nix-store-refs.sh ~/.conan2-nix
|
||||
```
|
||||
|
||||
It works on Linux too, but asserts something narrower there: the toolchain always
|
||||
writes the store into `PT_INTERP` and `RUNPATH`, and CI builds inside an image
|
||||
whose store is fixed for its lifetime, so that is fine. Only the binaries
|
||||
[`PatchNixBinary.cmake`](../../cmake/PatchNixBinary.cmake) retargets to the
|
||||
system loader have to be clean, and those are what CI checks:
|
||||
|
||||
```bash
|
||||
bin/check-nix-store-refs.sh build/xrpld
|
||||
```
|
||||
|
||||
### The libresolv stub
|
||||
|
||||
This is not hypothetical: `xrpld` used to be caught by it. The c-ares package
|
||||
tells the linker to pass `-lresolv`, and nixpkgs keeps `libresolv` out of the
|
||||
macOS SDK and ships it as an ordinary store dylib — so every Nix-built `xrpld`
|
||||
recorded a `/nix/store/…-libresolv-93/lib/libresolv.9.dylib` load command and
|
||||
stopped running once that path was collected. Nothing in the link uses a single
|
||||
symbol from it.
|
||||
|
||||
Both environments now put a stub on the linker search path
|
||||
(`libresolvSystemStub` in [`nix/darwin.nix`](../../nix/darwin.nix)): the
|
||||
same library with its install name set to `/usr/lib/libresolv.9.dylib`, which is
|
||||
exactly the load command the Apple Clang build records.
|
||||
|
||||
Package IDs did not change, so Conan keeps serving anything built before the
|
||||
stub landed. If a binary fails to start with `Library not loaded: /nix/store/…`,
|
||||
see [that entry](./nix_troubleshooting.md#library-not-loaded-nixstore-from-a-binary-that-used-to-work)
|
||||
in the troubleshooting guide.
|
||||
|
||||
## Automatic Activation with direnv
|
||||
|
||||
[direnv](https://direnv.net/) or [nix-direnv](https://github.com/nix-community/nix-direnv) can automatically activate the Nix development shell when you enter the repository directory.
|
||||
|
||||
88
docs/build/nix_troubleshooting.md
vendored
88
docs/build/nix_troubleshooting.md
vendored
@@ -131,91 +131,3 @@ once it picks up that rebuild, then re-run the `grep libgit2` check above to
|
||||
confirm it reports `1.9.4` or newer.
|
||||
|
||||
Until then, prefer the workarounds above.
|
||||
|
||||
## `wint_t` / `uint32_t` errors from the Nix libc++ headers
|
||||
|
||||
A build that mixes the Nix toolchain with the system SDK fails in libc++ itself,
|
||||
with errors that look nothing like your code:
|
||||
|
||||
```
|
||||
/nix/store/...-libcxx-.../include/c++/v1/cwchar:136:9: error: target of using declaration conflicts with declaration already in scope
|
||||
136 | using ::wint_t _LIBCPP_USING_IF_EXISTS;
|
||||
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/sys/_types/_wint_t.h:32:25: note: target of using declaration
|
||||
...
|
||||
error: use of undeclared identifier 'UINT32_C'
|
||||
```
|
||||
|
||||
The give-away is the second path: Nix's libc++ headers are being combined with
|
||||
the **Xcode Command Line Tools** SDK instead of the Nix one.
|
||||
|
||||
### Why it happens
|
||||
|
||||
`SDKROOT` and `DEVELOPER_DIR` are what point the toolchain at the Nix SDK, and
|
||||
they are not baked into the compiler — a dev shell gets them from the
|
||||
`apple-sdk` setup hook. CMake, finding neither, asks `xcrun`, which answers with
|
||||
the system SDK. Nix's `libc++` and Apple's headers then declare the same types
|
||||
twice.
|
||||
|
||||
### Fix
|
||||
|
||||
Run the build from inside the dev shell (`nix develop`), or from an environment
|
||||
that exports both variables. To confirm which SDK a configured build is using:
|
||||
|
||||
```bash
|
||||
grep -o '\-isysroot [^ ]*' build/compile_commands.json | sort -u
|
||||
```
|
||||
|
||||
It should print a `/nix/store/...-apple-sdk-*` path. If it prints
|
||||
`/Library/Developer/CommandLineTools/...`, re-configure from within the shell —
|
||||
CMake caches the sysroot, so an existing `build/` directory keeps the wrong one.
|
||||
|
||||
## `Library not loaded: /nix/store/…` from a binary that used to work
|
||||
|
||||
A binary stops starting after a `nix flake update`, or after
|
||||
`nix-collect-garbage` removes the paths the previous toolchain used:
|
||||
|
||||
```
|
||||
dyld[57271]: Library not loaded: /nix/store/…-libresolv-93/lib/libresolv.9.dylib
|
||||
```
|
||||
|
||||
[`bin/check-nix-store-refs.sh`](../../bin/check-nix-store-refs.sh) finds the same
|
||||
thing without having to run anything, and names the file:
|
||||
|
||||
```
|
||||
$ bin/check-nix-store-refs.sh ~/.conan2-nix
|
||||
::error file=/Users/you/.conan2-nix/p/b/c-area24ded30c388c/p/bin/adig::references the Nix store at run time
|
||||
/Users/you/.conan2-nix/p/b/c-area24ded30c388c/p/bin/adig
|
||||
/nix/store/p4lp3xq4imd1qzqh08x8vcq2zfhi7rca-libresolv-93/lib/libresolv.9.dylib
|
||||
/Users/you/.conan2-nix: checked 135, skipped 2495, 1 with Nix store references.
|
||||
```
|
||||
|
||||
Conan's cache folders are named after a truncated package name plus a hash, so
|
||||
ask Conan which package the offending one belongs to — pass the folder holding
|
||||
the hash, not the file itself:
|
||||
|
||||
```
|
||||
$ conan cache ref ~/.conan2-nix/p/b/c-area24ded30c388c
|
||||
c-ares/1.34.6#545240bb1c40e2cacd4362d6b8967650:dab5992496abe6d219defb7986ecbf367615a5e5#…
|
||||
```
|
||||
|
||||
### Why it happens
|
||||
|
||||
The binary records a store path that no longer exists. Nothing we build should:
|
||||
see [Prebuilt packages](./nix.md#prebuilt-packages) for why, and
|
||||
`libresolvSystemStub` in [`nix/darwin.nix`](../../nix/darwin.nix) for the one
|
||||
dependency that needed help to comply.
|
||||
|
||||
A Conan package ID does not encode the nixpkgs revision, so a package built
|
||||
before that stub existed stays in your local cache and keeps being reused. The
|
||||
dev shell is also what tends to produce one: it is a slightly _less_ isolated
|
||||
build environment than CI's, because `mkShell` puts every tool's headers and
|
||||
libraries on the compiler's search path — which is how c-ares found the Nix
|
||||
`libresolv` in the first place.
|
||||
|
||||
### Fix
|
||||
|
||||
Drop that package and let Conan refetch or rebuild it:
|
||||
|
||||
```bash
|
||||
conan remove 'c-ares/*'
|
||||
```
|
||||
|
||||
144
docs/install.md
144
docs/install.md
@@ -1,144 +0,0 @@
|
||||
# Installing xrpld
|
||||
|
||||
> [!NOTE]
|
||||
> These instructions apply to packages published from 2026-08-19 onwards.
|
||||
> For xrpld 3.3.0 and earlier see [install-legacy.md](./install-legacy.md).
|
||||
|
||||
`xrpld` is published as DEB and RPM packages for 64-bit x86 Linux.
|
||||
Use APT on Debian-based distributions such as Debian and Ubuntu,
|
||||
and YUM on Red Hat-based distributions such as RHEL, AlmaLinux, and Rocky Linux.
|
||||
To build from source instead, see [BUILD.md](../BUILD.md).
|
||||
|
||||
## Release channels
|
||||
|
||||
Packages are published to four channels:
|
||||
|
||||
- `stable` - the latest production release
|
||||
- `unstable` - release candidates
|
||||
- `experimental` - beta builds
|
||||
- `develop` - every push to the [`develop` branch](https://github.com/XRPLF/rippled/tree/develop)
|
||||
|
||||
See [Publishing packages](../package/README.md#publishing-packages) for how channels are produced.
|
||||
|
||||
The instructions below use `stable`.
|
||||
To follow another channel, replace `stable` with its name
|
||||
wherever it appears in the repository configuration.
|
||||
|
||||
> [!WARNING]
|
||||
> Channels other than `stable` may be broken at any time.
|
||||
> Do not use them for production servers.
|
||||
|
||||
## Install the xrpld package
|
||||
|
||||
### With the APT package manager
|
||||
|
||||
1. Install utilities:
|
||||
|
||||
```bash
|
||||
sudo apt update -y
|
||||
sudo apt install -y apt-transport-https ca-certificates curl gnupg
|
||||
```
|
||||
|
||||
2. Add the XRPL Foundation package-signing key to your list of trusted keys:
|
||||
|
||||
```bash
|
||||
sudo install -d -m 0755 /etc/apt/keyrings
|
||||
sudo curl -fsS https://packages.xrplf.org/xrplf.asc -o /etc/apt/keyrings/xrplf.asc
|
||||
```
|
||||
|
||||
3. Check the fingerprint of the newly-added key:
|
||||
|
||||
```bash
|
||||
gpg --show-keys /etc/apt/keyrings/xrplf.asc
|
||||
```
|
||||
|
||||
The output should be:
|
||||
|
||||
```text
|
||||
pub rsa4096 2026-08-18 [SC]
|
||||
B655416741221F780FBCFBC9AA84D41A11D29FA9
|
||||
uid XRPLF Packages <distribution@xrplf.org>
|
||||
```
|
||||
|
||||
In particular, make sure that the fingerprint matches.
|
||||
|
||||
4. Add the repository, using the channel you picked in [Release channels](#release-channels):
|
||||
|
||||
```bash
|
||||
echo "deb [signed-by=/etc/apt/keyrings/xrplf.asc] https://packages.xrplf.org/repository/deb-stable any main" | \
|
||||
sudo tee /etc/apt/sources.list.d/xrplf.list
|
||||
```
|
||||
|
||||
5. Fetch the repository:
|
||||
|
||||
```bash
|
||||
sudo apt -y update
|
||||
```
|
||||
|
||||
6. Install the `xrpld` software package:
|
||||
|
||||
```bash
|
||||
sudo apt -y install xrpld
|
||||
```
|
||||
|
||||
### With the YUM package manager
|
||||
|
||||
1. Add the XRPL Foundation package-signing key:
|
||||
|
||||
```bash
|
||||
sudo rpm --import https://packages.xrplf.org/xrplf.asc
|
||||
```
|
||||
|
||||
2. Add the repository, using the channel you picked in [Release channels](#release-channels):
|
||||
|
||||
```bash
|
||||
cat << REPOFILE | sudo tee /etc/yum.repos.d/xrplf.repo
|
||||
[xrplf-stable]
|
||||
name=XRP Ledger Packages
|
||||
enabled=1
|
||||
baseurl=https://packages.xrplf.org/repository/rpm-stable/
|
||||
gpgcheck=1
|
||||
repo_gpgcheck=1
|
||||
gpgkey=https://packages.xrplf.org/xrplf.asc
|
||||
REPOFILE
|
||||
```
|
||||
|
||||
`gpgcheck=1` verifies each package against the key above.
|
||||
`repo_gpgcheck=1` verifies the repository metadata, which the server signs with the same key.
|
||||
|
||||
3. Install the `xrpld` package:
|
||||
|
||||
```bash
|
||||
sudo yum install -y xrpld
|
||||
```
|
||||
|
||||
## The xrpld service
|
||||
|
||||
Both package managers install a systemd unit and enable it, so `xrpld` starts on boot.
|
||||
Check whether it is already running:
|
||||
|
||||
```bash
|
||||
systemctl status xrpld.service
|
||||
```
|
||||
|
||||
The APT packages start it immediately as well; the YUM packages do not, so start it yourself:
|
||||
|
||||
```bash
|
||||
sudo systemctl start xrpld.service
|
||||
```
|
||||
|
||||
### Optional: binding to privileged ports
|
||||
|
||||
To serve incoming API requests on port 80 or 443, grant the service the capability to bind them.
|
||||
You must also update the config file's port settings.
|
||||
|
||||
```bash
|
||||
sudo install -d -m 0755 /etc/systemd/system/xrpld.service.d
|
||||
sudo tee /etc/systemd/system/xrpld.service.d/privileged-ports.conf >/dev/null <<'EOF'
|
||||
[Service]
|
||||
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
|
||||
AmbientCapabilities=CAP_NET_BIND_SERVICE
|
||||
EOF
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl restart xrpld.service
|
||||
```
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <xrpl/basics/Blob.h>
|
||||
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/utility/string_view.hpp>
|
||||
|
||||
#include <array>
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
namespace beast::rfc2616 {
|
||||
@@ -187,7 +186,7 @@ splitCommas(FwdIt first, FwdIt last)
|
||||
|
||||
template <class Result = std::vector<std::string>>
|
||||
Result
|
||||
splitCommas(std::string_view s)
|
||||
splitCommas(boost::beast::string_view const& s)
|
||||
{
|
||||
return splitCommas(s.begin(), s.end());
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <xrpl/basics/contract.h>
|
||||
|
||||
#include <boost/beast/core/string.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <boost/beast/core/string.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace json {
|
||||
|
||||
class Value;
|
||||
|
||||
using Output = std::function<void(std::string_view)>;
|
||||
using Output = std::function<void(boost::beast::string_view const&)>;
|
||||
|
||||
inline Output
|
||||
stringOutput(std::string& s)
|
||||
{
|
||||
return [&](std::string_view b) { s.append(b.data(), b.size()); };
|
||||
return [&](boost::beast::string_view const& b) { s.append(b.data(), b.size()); };
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -78,13 +78,6 @@ isVaultPseudoAccountFrozen(
|
||||
MPTIssue const& mptShare,
|
||||
std::uint8_t depth);
|
||||
|
||||
[[nodiscard]] bool
|
||||
isVaultPseudoAccountFrozen(
|
||||
ReadView const& view,
|
||||
AccountID const& account,
|
||||
SLE const& issuanceSle,
|
||||
std::uint8_t depth);
|
||||
|
||||
[[nodiscard]] bool
|
||||
isLPTokenFrozen(
|
||||
ReadView const& view,
|
||||
@@ -92,26 +85,6 @@ isLPTokenFrozen(
|
||||
Asset const& asset,
|
||||
Asset const& asset2);
|
||||
|
||||
/**
|
||||
* Check whether an AMM LPToken may be transferred between @p from and @p to.
|
||||
*
|
||||
* @p lpTokenIssuer is the issuer of the LPToken being moved. If it is not an
|
||||
* AMM account the token is not an LPToken and the transfer is unconditionally
|
||||
* permitted. Otherwise, for each MPT pool asset of that AMM, canTransfer() must
|
||||
* permit the transfer (which exempts the MPT issuer). Non-MPT pool assets are
|
||||
* always transferable by this check, so it is implicitly gated by
|
||||
* featureMPTokensV2 (MPTs can only be AMM pool assets once V2 is enabled).
|
||||
*
|
||||
* @return tesSUCCESS if permitted, otherwise the canTransfer() failure code
|
||||
* (e.g. tecNO_AUTH) of the first MPT pool asset that disallows it.
|
||||
*/
|
||||
[[nodiscard]] TER
|
||||
canTransferLPToken(
|
||||
ReadView const& view,
|
||||
AccountID const& from,
|
||||
AccountID const& to,
|
||||
AccountID const& lpTokenIssuer);
|
||||
|
||||
// Return the list of enabled amendments
|
||||
[[nodiscard]] std::set<uint256>
|
||||
getEnabledAmendments(ReadView const& view);
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/ledger/ApplyView.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Asset.h>
|
||||
#include <xrpl/protocol/LedgerFormats.h> // IWYU pragma: keep
|
||||
#include <xrpl/protocol/Protocol.h>
|
||||
@@ -22,7 +21,6 @@
|
||||
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
@@ -60,42 +58,6 @@ canApplyToBrokerCover(
|
||||
bool
|
||||
checkLendingProtocolDependencies(Rules const& rules, STTx const& tx);
|
||||
|
||||
/**
|
||||
* The accounts and asset that LoanManage::defaultLoan's fixCleanup3_4_0
|
||||
* freeze/lock exemption applies to.
|
||||
*
|
||||
* `defaultLoan` moves funds from the LoanBroker pseudo-account to the Vault
|
||||
* pseudo-account via `accountSend`. Since neither is the vault asset's
|
||||
* issuer, this is a third-party transfer that transits through the issuer in
|
||||
* two hops (broker -> issuer, issuer -> vault; see
|
||||
* `directSendNoLimitIOU`/`directSendNoLimitMPT`), so the exemption must cover
|
||||
* both the issuer/broker and issuer/vault pairs, not a direct broker/vault
|
||||
* pair. `asset` scopes it further to the vault's own currency/MPT issuance,
|
||||
* so an unrelated one the same accounts happen to hold is still protected.
|
||||
*/
|
||||
struct LoanDefaultFreezeExemptAccounts
|
||||
{
|
||||
AccountID issuer;
|
||||
AccountID broker;
|
||||
AccountID vault;
|
||||
Asset asset;
|
||||
};
|
||||
|
||||
/**
|
||||
* Resolves the accounts and asset a LoanManage default transaction is
|
||||
* exempt from freeze/lock for.
|
||||
*
|
||||
* @param view Ledger view used to resolve the Loan -> LoanBroker -> Vault
|
||||
* chain.
|
||||
* @param tx The transaction under invariant review.
|
||||
* @return The exempt accounts and asset if `tx` is a `ttLOAN_MANAGE`
|
||||
* transaction with the `tfLoanDefault` flag set, `fixCleanup3_4_0` is
|
||||
* enabled, and the loan/broker/vault objects it references can all be
|
||||
* resolved; `std::nullopt` otherwise.
|
||||
*/
|
||||
[[nodiscard]] std::optional<LoanDefaultFreezeExemptAccounts>
|
||||
getLoanDefaultFreezeExemptAccounts(ReadView const& view, STTx const& tx);
|
||||
|
||||
static constexpr std::uint32_t kSecondsInYear = 365 * 24 * 60 * 60;
|
||||
|
||||
Number
|
||||
|
||||
@@ -29,9 +29,6 @@ namespace xrpl {
|
||||
[[nodiscard]] bool
|
||||
isGlobalFrozen(ReadView const& view, MPTIssue const& mptIssue);
|
||||
|
||||
[[nodiscard]] bool
|
||||
isGlobalFrozen(SLE const& issuanceSle);
|
||||
|
||||
/**
|
||||
* Returns true if @p account's MPToken for @p mptIssue carries the
|
||||
* individual-lock flag (lsfMPTLocked).
|
||||
@@ -43,29 +40,9 @@ isGlobalFrozen(SLE const& issuanceSle);
|
||||
* receive tokens — it combines isIndividualFrozen, isGlobalFrozen, and
|
||||
* isVaultPseudoAccountFrozen into a single complete check.
|
||||
*/
|
||||
|
||||
[[nodiscard]] bool
|
||||
isIndividualFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssue);
|
||||
|
||||
[[nodiscard]] bool
|
||||
isIndividualFrozen(SLE const& mptSle);
|
||||
|
||||
/**
|
||||
* Returns true if @p account cannot send or receive tokens of @p mptIssue
|
||||
* because a freeze applies. This is the complete check callers should use
|
||||
* before moving MPT value: it combines @ref isGlobalFrozen (issuance-level
|
||||
* lock), @ref isIndividualFrozen (per-holder lock bit), and the transitive
|
||||
* vault pseudo-account check (if @p mptIssue is a vault share, the underlying
|
||||
* asset is checked, and so on recursively up to @c maxAssetCheckDepth).
|
||||
*
|
||||
* The @c SLE overload takes an already-loaded ltMPTOKEN or ltMPTOKEN_ISSUANCE
|
||||
* ledger entry; for ltMPTOKEN it can skip the per-holder individual-lock lookup.
|
||||
* @ref isAnyFrozen answers the same question for a set of accounts and returns true
|
||||
* if the freeze applies to any of them.
|
||||
*
|
||||
* @param depth Current recursion depth for the vault-share walk. Callers
|
||||
* outside this module should leave it at the default.
|
||||
*/
|
||||
[[nodiscard]] bool
|
||||
isFrozen(
|
||||
ReadView const& view,
|
||||
@@ -73,18 +50,6 @@ isFrozen(
|
||||
MPTIssue const& mptIssue,
|
||||
std::uint8_t depth = 0);
|
||||
|
||||
/**
|
||||
* SLE overload: pass an already-loaded ltMPTOKEN (holder row) or
|
||||
* ltMPTOKEN_ISSUANCE to reuse it for the freeze checks and avoid re-reading
|
||||
* the same object. For an ltMPTOKEN, @p sle is used directly for the
|
||||
* individual-lock check and the issuance is read once for global-freeze and
|
||||
* vault-pseudo-account. For an ltMPTOKEN_ISSUANCE, @p sle is used directly
|
||||
* for global-freeze and vault-pseudo-account, and the caller's holder row is
|
||||
* read for the individual-lock check.
|
||||
*/
|
||||
[[nodiscard]] bool
|
||||
isFrozen(ReadView const& view, AccountID const& account, SLE const& sle, std::uint8_t depth = 0);
|
||||
|
||||
[[nodiscard]] bool
|
||||
isAnyFrozen(
|
||||
ReadView const& view,
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/basics/Number.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Asset.h>
|
||||
#include <xrpl/protocol/Protocol.h>
|
||||
#include <xrpl/protocol/STAmount.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
@@ -57,38 +55,6 @@ enum class TruncateShares : bool { No = false, Yes = true };
|
||||
*/
|
||||
enum class WaiveUnrealizedLoss : bool { No = false, Yes = true };
|
||||
|
||||
/**
|
||||
* Returns the effective total of assets backing outstanding shares for the
|
||||
* purposes of a withdrawal, i.e. sfAssetsTotal, discounted by sfLossUnrealized
|
||||
* unless waived. This is the numerator used by both withdraw conversion
|
||||
* helpers (assetsToSharesWithdraw and sharesToAssetsWithdraw) to compute the
|
||||
* share/asset exchange rate.
|
||||
*
|
||||
* @param vault The vault SLE.
|
||||
* @param waive Whether to waive (i.e. not subtract) the vault's unrealized
|
||||
* loss.
|
||||
*/
|
||||
[[nodiscard]] Number
|
||||
assetsTotalForWithdrawal(SLE::const_ref vault, WaiveUnrealizedLoss waive);
|
||||
|
||||
/**
|
||||
* Returns whether debiting `amount` from `total` — the current value of a
|
||||
* vault's sfAssetsTotal or sfAssetsAvailable field — would canonicalize back
|
||||
* to the exact same STAmount value it started at. This happens when a
|
||||
* genuinely non-zero debit is dust relative to a `total` large enough to
|
||||
* exceed STAmount's significant-digit precision: the shares still move, but
|
||||
* the stored total doesn't change, which otherwise trips the ValidVault
|
||||
* invariant after the fact instead of failing cleanly upfront.
|
||||
*
|
||||
* @param asset The vault's underlying asset, used to canonicalize both sides
|
||||
* the same way the ledger will when the field is stored.
|
||||
* @param total The field's current value.
|
||||
* @param amount The amount to debit. A value of zero always returns false;
|
||||
* that case is rejected separately and unconditionally.
|
||||
*/
|
||||
[[nodiscard]] bool
|
||||
debitIsNonZeroDust(Asset const& asset, Number const& total, Number const& amount);
|
||||
|
||||
/**
|
||||
* From the perspective of a vault, return the number of shares to demand from
|
||||
* the depositor when they ask to withdraw a fixed amount of assets. Since
|
||||
|
||||
@@ -8,11 +8,11 @@
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/ssl.hpp>
|
||||
#include <boost/format.hpp>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/tls1.h>
|
||||
|
||||
#include <format>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
@@ -38,8 +38,8 @@ public:
|
||||
|
||||
if (ec && sslVerifyDir.empty())
|
||||
{
|
||||
Throw<std::runtime_error>(
|
||||
std::format("Failed to set_default_verify_paths: {}", ec.message()));
|
||||
Throw<std::runtime_error>(boost::str(
|
||||
boost::format("Failed to set_default_verify_paths: %s") % ec.message()));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -54,7 +54,7 @@ public:
|
||||
if (ec)
|
||||
{
|
||||
Throw<std::runtime_error>(
|
||||
std::format("Failed to add verify path: {}", ec.message()));
|
||||
boost::str(boost::format("Failed to add verify path: %s") % ec.message()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
syntax = "proto2";
|
||||
package protocol;
|
||||
|
||||
// Unused numbers in the list below may have been used previously. Please don't
|
||||
// reassign them for reuse unless you are 100% certain that there won't be a
|
||||
// conflict. Even if you're sure, it's probably best to assign a new type.
|
||||
enum MessageType {
|
||||
// Previously used - don't reuse.
|
||||
reserved 0 to 1, 4, 6 to 14, 16 to 29, 36 to 40, 43 to 54, 61 to 62;
|
||||
|
||||
mtMANIFESTS = 2;
|
||||
mtPING = 3;
|
||||
mtCLUSTER = 5;
|
||||
@@ -17,6 +17,7 @@ enum MessageType {
|
||||
mtHAVE_SET = 35;
|
||||
mtVALIDATION = 41;
|
||||
mtGET_OBJECTS = 42;
|
||||
mtVALIDATOR_LIST = 54;
|
||||
mtSQUELCH = 55;
|
||||
mtVALIDATOR_LIST_COLLECTION = 56;
|
||||
mtPROOF_PATH_REQ = 57;
|
||||
@@ -161,6 +162,14 @@ message TMHaveTransactionSet {
|
||||
required bytes hash = 2;
|
||||
}
|
||||
|
||||
// Validator list (UNL)
|
||||
message TMValidatorList {
|
||||
required bytes manifest = 1;
|
||||
required bytes blob = 2;
|
||||
required bytes signature = 3;
|
||||
required uint32 version = 4;
|
||||
}
|
||||
|
||||
// Validator List v2
|
||||
message ValidatorBlobInfo {
|
||||
optional bytes manifest = 1;
|
||||
|
||||
@@ -2,9 +2,6 @@
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <format>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
@@ -12,29 +9,9 @@ namespace xrpl {
|
||||
|
||||
// These pragmas are built at startup and applied to all database
|
||||
// connections, unless otherwise noted.
|
||||
//
|
||||
// They are exposed as functions rather than as format-string constants so
|
||||
// that the un-substituted template can never reach sqlite: an unrecognized
|
||||
// pragma value is silently ignored, so forgetting to interpolate would
|
||||
// leave the setting at its default instead of failing loudly.
|
||||
[[nodiscard]] inline std::string
|
||||
commonDbPragmaJournal(std::string_view journalMode)
|
||||
{
|
||||
return std::format("PRAGMA journal_mode={};", journalMode);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline std::string
|
||||
commonDbPragmaSync(std::string_view synchronous)
|
||||
{
|
||||
return std::format("PRAGMA synchronous={};", synchronous);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline std::string
|
||||
commonDbPragmaTemp(std::string_view tempStore)
|
||||
{
|
||||
return std::format("PRAGMA temp_store={};", tempStore);
|
||||
}
|
||||
|
||||
inline constexpr char const* kCommonDbPragmaJournal{"PRAGMA journal_mode=%s;"};
|
||||
inline constexpr char const* kCommonDbPragmaSync{"PRAGMA synchronous=%s;"};
|
||||
inline constexpr char const* kCommonDbPragmaTemp{"PRAGMA temp_store=%s;"};
|
||||
// A warning will be logged if any lower-safety sqlite tuning settings
|
||||
// are used and at least this much ledger history is configured. This
|
||||
// includes full history nodes. This is because such a large amount of
|
||||
|
||||
@@ -10,10 +10,6 @@
|
||||
#include <xrpl/rdb/DatabaseCon.h>
|
||||
#include <xrpl/server/Manifest.h>
|
||||
|
||||
// boost::optional (not std::optional) appears in the declarations below,
|
||||
// because SOCI's into()/use() bindings only support boost::optional.
|
||||
#include <boost/optional/optional.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#include <iterator>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@@ -63,7 +62,8 @@ private:
|
||||
bool pingActive_ = false;
|
||||
boost::beast::websocket::ping_data payload_;
|
||||
error_code ec_;
|
||||
std::function<void(boost::beast::websocket::frame_type, std::string_view)> controlCallback_;
|
||||
std::function<void(boost::beast::websocket::frame_type, boost::beast::string_view)>
|
||||
controlCallback_;
|
||||
|
||||
public:
|
||||
template <class Body, class Headers>
|
||||
@@ -151,7 +151,7 @@ protected:
|
||||
onPing(error_code const& ec);
|
||||
|
||||
void
|
||||
onPingPong(boost::beast::websocket::frame_type kind, std::string_view payload);
|
||||
onPingPong(boost::beast::websocket::frame_type kind, boost::beast::string_view payload);
|
||||
|
||||
void
|
||||
onTimer(error_code ec);
|
||||
@@ -189,9 +189,9 @@ BaseWSPeer<Handler, Impl>::run()
|
||||
impl().ws_.set_option(port().pmdOptions);
|
||||
// Must manage the control callback memory outside of the `control_callback`
|
||||
// function
|
||||
controlCallback_ = [this](boost::beast::websocket::frame_type kind, std::string_view payload) {
|
||||
onPingPong(kind, payload);
|
||||
};
|
||||
controlCallback_ = [this](
|
||||
boost::beast::websocket::frame_type kind,
|
||||
boost::beast::string_view payload) { onPingPong(kind, payload); };
|
||||
impl().ws_.control_callback(controlCallback_);
|
||||
startTimer();
|
||||
closeOnTimer_ = true;
|
||||
@@ -430,11 +430,11 @@ template <class Handler, class Impl>
|
||||
void
|
||||
BaseWSPeer<Handler, Impl>::onPingPong(
|
||||
boost::beast::websocket::frame_type kind,
|
||||
std::string_view payload)
|
||||
boost::beast::string_view payload)
|
||||
{
|
||||
if (kind == boost::beast::websocket::frame_type::pong)
|
||||
{
|
||||
std::string_view const p(payload_.begin(), payload_.size());
|
||||
boost::beast::string_view const p(payload_.begin());
|
||||
if (payload == p)
|
||||
{
|
||||
closeOnTimer_ = false;
|
||||
|
||||
@@ -484,36 +484,31 @@ private:
|
||||
|
||||
// returns the first item at or below this node
|
||||
SHAMapLeafNode*
|
||||
firstBelow(SHAMapTreeNodePtr node, SharedPtrNodeStack& stack, unsigned int branch = 0u) const;
|
||||
firstBelow(SHAMapTreeNodePtr node, SharedPtrNodeStack& stack, int branch = 0) const;
|
||||
|
||||
// returns the last item at or below this node
|
||||
SHAMapLeafNode*
|
||||
lastBelow(
|
||||
SHAMapTreeNodePtr node,
|
||||
SharedPtrNodeStack& stack,
|
||||
unsigned int branch = kBranchFactor) const;
|
||||
|
||||
// direction in which belowHelper scans an inner node's branches
|
||||
enum class BelowDirection { First, Last };
|
||||
lastBelow(SHAMapTreeNodePtr node, SharedPtrNodeStack& stack, int branch = kBranchFactor) const;
|
||||
|
||||
// helper function for firstBelow and lastBelow
|
||||
SHAMapLeafNode*
|
||||
belowHelper(
|
||||
SHAMapTreeNodePtr node,
|
||||
SharedPtrNodeStack& stack,
|
||||
unsigned int branch,
|
||||
BelowDirection direction) const;
|
||||
int branch,
|
||||
std::tuple<int, std::function<bool(int)>, std::function<void(int&)>> const& loopParams)
|
||||
const;
|
||||
|
||||
// Simple descent
|
||||
// Get a child of the specified node
|
||||
SHAMapTreeNode*
|
||||
descend(SHAMapInnerNode*, unsigned int branch) const;
|
||||
descend(SHAMapInnerNode*, int branch) const;
|
||||
SHAMapTreeNode*
|
||||
descendThrow(SHAMapInnerNode*, unsigned int branch) const;
|
||||
descendThrow(SHAMapInnerNode*, int branch) const;
|
||||
SHAMapTreeNodePtr
|
||||
descend(SHAMapInnerNode&, unsigned int branch) const;
|
||||
descend(SHAMapInnerNode&, int branch) const;
|
||||
SHAMapTreeNodePtr
|
||||
descendThrow(SHAMapInnerNode&, unsigned int branch) const;
|
||||
descendThrow(SHAMapInnerNode&, int branch) const;
|
||||
|
||||
// Descend with filter
|
||||
// If pending, callback is called as if it called fetchNodeNT
|
||||
@@ -521,7 +516,7 @@ private:
|
||||
SHAMapTreeNode*
|
||||
descendAsync(
|
||||
SHAMapInnerNode* parent,
|
||||
unsigned int branch,
|
||||
int branch,
|
||||
SHAMapSyncFilter const* filter,
|
||||
bool& pending,
|
||||
descendCallback&&) const;
|
||||
@@ -530,13 +525,13 @@ private:
|
||||
descend(
|
||||
SHAMapInnerNode* parent,
|
||||
SHAMapNodeID const& parentID,
|
||||
unsigned int branch,
|
||||
int branch,
|
||||
SHAMapSyncFilter const* filter) const;
|
||||
|
||||
// Non-storing
|
||||
// Does not hook the returned node to its parent
|
||||
SHAMapTreeNodePtr
|
||||
descendNoStore(SHAMapInnerNode&, unsigned int branch) const;
|
||||
descendNoStore(SHAMapInnerNode&, int branch) const;
|
||||
|
||||
/**
|
||||
* If there is only one leaf below this node, get its contents
|
||||
@@ -586,8 +581,8 @@ private:
|
||||
using StackEntry = std::tuple<
|
||||
SHAMapInnerNode*, // pointer to the node
|
||||
SHAMapNodeID, // the node's ID
|
||||
unsigned int, // which child we check first
|
||||
unsigned int, // which child we check next
|
||||
int, // while child we check first
|
||||
int, // which child we check next
|
||||
bool>; // whether we've found any missing children yet
|
||||
|
||||
// We explicitly choose to specify the use of std::deque here, because
|
||||
@@ -601,7 +596,7 @@ private:
|
||||
using DeferredNode = std::tuple<
|
||||
SHAMapInnerNode*, // parent node
|
||||
SHAMapNodeID, // parent node ID
|
||||
unsigned int, // branch
|
||||
int, // branch
|
||||
SHAMapTreeNodePtr>; // node
|
||||
|
||||
int deferred;
|
||||
|
||||
@@ -62,8 +62,8 @@ private:
|
||||
*
|
||||
* @param i index of the requested child
|
||||
*/
|
||||
std::optional<unsigned int>
|
||||
getChildIndex(unsigned int i) const;
|
||||
std::optional<int>
|
||||
getChildIndex(int i) const;
|
||||
|
||||
/**
|
||||
* Call the `f` callback for all 16 (branchFactor) branches - even if
|
||||
@@ -125,28 +125,28 @@ public:
|
||||
isEmpty() const;
|
||||
|
||||
bool
|
||||
isEmptyBranch(unsigned int branch) const;
|
||||
isEmptyBranch(int m) const;
|
||||
|
||||
unsigned int
|
||||
int
|
||||
getBranchCount() const;
|
||||
|
||||
SHAMapHash const&
|
||||
getChildHash(unsigned int branch) const;
|
||||
getChildHash(int m) const;
|
||||
|
||||
void
|
||||
setChild(unsigned int branch, SHAMapTreeNodePtr child);
|
||||
setChild(int m, SHAMapTreeNodePtr child);
|
||||
|
||||
void
|
||||
shareChild(unsigned int branch, SHAMapTreeNodePtr const& child);
|
||||
shareChild(int m, SHAMapTreeNodePtr const& child);
|
||||
|
||||
SHAMapTreeNode*
|
||||
getChildPointer(unsigned int branch);
|
||||
getChildPointer(int branch);
|
||||
|
||||
SHAMapTreeNodePtr
|
||||
getChild(unsigned int branch);
|
||||
getChild(int branch);
|
||||
|
||||
SHAMapTreeNodePtr
|
||||
canonicalizeChild(unsigned int branch, SHAMapTreeNodePtr node);
|
||||
canonicalizeChild(int branch, SHAMapTreeNodePtr node);
|
||||
|
||||
// sync functions
|
||||
bool
|
||||
@@ -190,12 +190,12 @@ SHAMapInnerNode::isEmpty() const
|
||||
}
|
||||
|
||||
inline bool
|
||||
SHAMapInnerNode::isEmptyBranch(unsigned int branch) const
|
||||
SHAMapInnerNode::isEmptyBranch(int m) const
|
||||
{
|
||||
return (isBranch_ & (1u << branch)) == 0u;
|
||||
return (isBranch_ & (1 << m)) == 0;
|
||||
}
|
||||
|
||||
inline unsigned int
|
||||
inline int
|
||||
SHAMapInnerNode::getBranchCount() const
|
||||
{
|
||||
return popcnt16(isBranch_);
|
||||
|
||||
@@ -53,21 +53,7 @@ public:
|
||||
}
|
||||
|
||||
[[nodiscard]] SHAMapNodeID
|
||||
getChildNodeID(unsigned int branch) const;
|
||||
|
||||
/**
|
||||
* Test whether this node ID lies on the path to the given leaf key
|
||||
*
|
||||
* A node at depth d identifies the tree path spelled by the first d
|
||||
* nibbles of its key, so any leaf beneath it must agree on that prefix.
|
||||
* A node ID that fails this test names a different subtree than the one
|
||||
* it was built for.
|
||||
*
|
||||
* @param key the key of a leaf below this node
|
||||
* @return whether this node ID is a prefix of the leaf key
|
||||
*/
|
||||
[[nodiscard]] bool
|
||||
isPrefixOf(uint256 const& key) const;
|
||||
getChildNodeID(unsigned int m) const;
|
||||
|
||||
/**
|
||||
* Create a SHAMapNodeID of a node with the depth of the node and
|
||||
@@ -78,7 +64,7 @@ public:
|
||||
* @return SHAMapNodeID of the node
|
||||
*/
|
||||
static SHAMapNodeID
|
||||
createID(unsigned int depth, uint256 const& key);
|
||||
createID(int depth, uint256 const& key);
|
||||
|
||||
/**
|
||||
* Comparison operators
|
||||
|
||||
@@ -219,11 +219,11 @@ public:
|
||||
*
|
||||
* @param i index of the requested child
|
||||
*/
|
||||
[[nodiscard]] std::optional<unsigned int>
|
||||
getChildIndex(std::uint16_t isBranch, unsigned int i) const;
|
||||
[[nodiscard]] std::optional<int>
|
||||
getChildIndex(std::uint16_t isBranch, int i) const;
|
||||
};
|
||||
|
||||
[[nodiscard]] inline unsigned int
|
||||
[[nodiscard]] inline int
|
||||
popcnt16(std::uint16_t a)
|
||||
{
|
||||
#if __cpp_lib_bitops
|
||||
@@ -234,11 +234,11 @@ popcnt16(std::uint16_t a)
|
||||
// fallback to table lookup
|
||||
static constexpr auto tbl = []() {
|
||||
std::array<std::uint8_t, 256> ret{};
|
||||
for (auto i = 0u; i != 256u; ++i)
|
||||
for (int i = 0; i != 256; ++i)
|
||||
{
|
||||
for (auto j = 0u; j != 8u; ++j)
|
||||
for (int j = 0; j != 8; ++j)
|
||||
{
|
||||
if (i & (1u << j))
|
||||
if (i & (1 << j))
|
||||
ret[i]++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,11 +22,6 @@ static_assert(
|
||||
static_assert(
|
||||
kBoundaries.back() == SHAMapInnerNode::kBranchFactor,
|
||||
"Last element of boundaries must be number of children in a dense array");
|
||||
static_assert(
|
||||
kBoundaries.front() >= 1,
|
||||
"TaggedPointer.ipp subtracts 1 from a numAllocated value derived from "
|
||||
"kBoundaries, as an unsigned quantity, in several places; the smallest "
|
||||
"boundary must stay non-zero or those subtractions underflow.");
|
||||
|
||||
// Terminology: A chunk is the memory being allocated from a block. A block
|
||||
// contains multiple chunks. This is the terminology the boost documentation
|
||||
@@ -153,16 +148,16 @@ TaggedPointer::iterChildren(std::uint16_t isBranch, F&& f) const
|
||||
if (numAllocated == SHAMapInnerNode::kBranchFactor)
|
||||
{
|
||||
// dense case
|
||||
for (auto i = 0u; i < SHAMapInnerNode::kBranchFactor; ++i)
|
||||
for (int i = 0; i < SHAMapInnerNode::kBranchFactor; ++i)
|
||||
f(hashes[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// sparse case
|
||||
auto curHashI = 0u;
|
||||
for (auto i = 0u; i < SHAMapInnerNode::kBranchFactor; ++i)
|
||||
int curHashI = 0;
|
||||
for (int i = 0; i < SHAMapInnerNode::kBranchFactor; ++i)
|
||||
{
|
||||
if ((1u << i) & isBranch)
|
||||
if ((1 << i) & isBranch)
|
||||
{
|
||||
f(hashes[curHashI++]);
|
||||
}
|
||||
@@ -181,9 +176,9 @@ TaggedPointer::iterNonEmptyChildIndexes(std::uint16_t isBranch, F&& f) const
|
||||
if (capacity() == SHAMapInnerNode::kBranchFactor)
|
||||
{
|
||||
// dense case
|
||||
for (auto i = 0u; i < SHAMapInnerNode::kBranchFactor; ++i)
|
||||
for (int i = 0; i < SHAMapInnerNode::kBranchFactor; ++i)
|
||||
{
|
||||
if ((1u << i) & isBranch)
|
||||
if ((1 << i) & isBranch)
|
||||
{
|
||||
f(i, i);
|
||||
}
|
||||
@@ -192,10 +187,10 @@ TaggedPointer::iterNonEmptyChildIndexes(std::uint16_t isBranch, F&& f) const
|
||||
else
|
||||
{
|
||||
// sparse case
|
||||
auto curHashI = 0u;
|
||||
for (auto i = 0u; i < SHAMapInnerNode::kBranchFactor; ++i)
|
||||
int curHashI = 0;
|
||||
for (int i = 0; i < SHAMapInnerNode::kBranchFactor; ++i)
|
||||
{
|
||||
if ((1u << i) & isBranch)
|
||||
if ((1 << i) & isBranch)
|
||||
{
|
||||
f(i, curHashI++);
|
||||
}
|
||||
@@ -221,14 +216,14 @@ TaggedPointer::destroyHashesAndChildren()
|
||||
deallocateArrays(tag, ptr);
|
||||
}
|
||||
|
||||
inline std::optional<unsigned int>
|
||||
TaggedPointer::getChildIndex(std::uint16_t isBranch, unsigned int i) const
|
||||
inline std::optional<int>
|
||||
TaggedPointer::getChildIndex(std::uint16_t isBranch, int i) const
|
||||
{
|
||||
if (isDense())
|
||||
return i;
|
||||
|
||||
// Sparse case
|
||||
if ((isBranch & (1u << i)) == 0u)
|
||||
if ((isBranch & (1 << i)) == 0)
|
||||
{
|
||||
// Empty branch. Sparse children do not store empty branches
|
||||
return {};
|
||||
@@ -278,10 +273,10 @@ inline TaggedPointer::TaggedPointer(
|
||||
*this = std::move(other);
|
||||
auto [srcDstNumAllocated, srcDstHashes, srcDstChildren] = getHashesAndChildren();
|
||||
bool const srcDstIsDense = isDense();
|
||||
auto srcDstIndex = 0u;
|
||||
for (auto i = 0u; i < SHAMapInnerNode::kBranchFactor; ++i)
|
||||
int srcDstIndex = 0;
|
||||
for (int i = 0; i < SHAMapInnerNode::kBranchFactor; ++i)
|
||||
{
|
||||
auto const mask = (1u << i);
|
||||
auto const mask = (1 << i);
|
||||
bool const inSrc = (srcBranches & mask) != 0;
|
||||
bool const inDst = (dstBranches & mask) != 0;
|
||||
if (inSrc && inDst)
|
||||
@@ -303,13 +298,13 @@ inline TaggedPointer::TaggedPointer(
|
||||
// sparse
|
||||
// need to shift all the elements to the left by
|
||||
// one
|
||||
for (auto c = srcDstIndex; c + 1 < srcDstNumAllocated; ++c)
|
||||
for (int c = srcDstIndex; c < srcDstNumAllocated - 1; ++c)
|
||||
{
|
||||
srcDstHashes[c] = srcDstHashes[c + 1];
|
||||
srcDstChildren[c] = std::move(srcDstChildren[c + 1]);
|
||||
}
|
||||
srcDstHashes[srcDstNumAllocated - 1u].zero();
|
||||
srcDstChildren[srcDstNumAllocated - 1u].reset();
|
||||
srcDstHashes[srcDstNumAllocated - 1].zero();
|
||||
srcDstChildren[srcDstNumAllocated - 1].reset();
|
||||
// do not increment the index
|
||||
}
|
||||
}
|
||||
@@ -326,7 +321,7 @@ inline TaggedPointer::TaggedPointer(
|
||||
// sparse
|
||||
// need to create a hole by shifting all the elements to the
|
||||
// right by one
|
||||
for (auto c = srcDstNumAllocated - 1u; c > srcDstIndex; --c)
|
||||
for (int c = srcDstNumAllocated - 1; c > srcDstIndex; --c)
|
||||
{
|
||||
srcDstHashes[c] = srcDstHashes[c - 1];
|
||||
srcDstChildren[c] = std::move(srcDstChildren[c - 1]);
|
||||
@@ -357,10 +352,10 @@ inline TaggedPointer::TaggedPointer(
|
||||
auto [srcNumAllocated, srcHashes, srcChildren] = src.getHashesAndChildren();
|
||||
bool const srcIsDense = src.isDense();
|
||||
bool const dstIsDense = dst.isDense();
|
||||
auto srcIndex = 0u, dstIndex = 0u;
|
||||
for (auto i = 0u; i < SHAMapInnerNode::kBranchFactor; ++i)
|
||||
int srcIndex = 0, dstIndex = 0;
|
||||
for (int i = 0; i < SHAMapInnerNode::kBranchFactor; ++i)
|
||||
{
|
||||
auto const mask = (1u << i);
|
||||
auto const mask = (1 << i);
|
||||
bool const inSrc = (srcBranches & mask) != 0;
|
||||
bool const inDst = (dstBranches & mask) != 0;
|
||||
if (inSrc && inDst)
|
||||
@@ -414,7 +409,7 @@ inline TaggedPointer::TaggedPointer(
|
||||
!dstIsDense || dstIndex == dstNumAllocated,
|
||||
"xrpl::TaggedPointer::TaggedPointer(TaggedPointer&& ...) : "
|
||||
"non-sparse or valid sparse");
|
||||
for (auto i = dstIndex; i < dstNumAllocated; ++i)
|
||||
for (int i = dstIndex; i < dstNumAllocated; ++i)
|
||||
{
|
||||
new (&dstHashes[i]) SHAMapHash{};
|
||||
new (&dstChildren[i]) SHAMapTreeNodePtr{};
|
||||
@@ -453,9 +448,9 @@ inline TaggedPointer::TaggedPointer(
|
||||
new (&newChildren[branchNum]) SHAMapTreeNodePtr{std::move(oldChildren[indexNum])};
|
||||
});
|
||||
// Run the constructors for the remaining elements
|
||||
for (auto i = 0u; i < SHAMapInnerNode::kBranchFactor; ++i)
|
||||
for (int i = 0; i < SHAMapInnerNode::kBranchFactor; ++i)
|
||||
{
|
||||
if (((1u << i) & isBranch) != 0u)
|
||||
if (((1 << i) & isBranch) != 0)
|
||||
continue;
|
||||
new (&newHashes[i]) SHAMapHash{};
|
||||
new (&newChildren[i]) SHAMapTreeNodePtr{};
|
||||
@@ -464,7 +459,7 @@ inline TaggedPointer::TaggedPointer(
|
||||
else
|
||||
{
|
||||
// new arrays are sparse, old arrays may be sparse or dense
|
||||
auto curCompressedIndex = 0u;
|
||||
int curCompressedIndex = 0;
|
||||
iterNonEmptyChildIndexes(isBranch, [&](auto branchNum, auto indexNum) {
|
||||
new (&newHashes[curCompressedIndex]) SHAMapHash{oldHashes[indexNum]};
|
||||
new (&newChildren[curCompressedIndex])
|
||||
@@ -472,7 +467,7 @@ inline TaggedPointer::TaggedPointer(
|
||||
++curCompressedIndex;
|
||||
});
|
||||
// Run the constructors for the remaining elements
|
||||
for (auto i = curCompressedIndex; i < newNumAllocated; ++i)
|
||||
for (int i = curCompressedIndex; i < newNumAllocated; ++i)
|
||||
{
|
||||
new (&newHashes[i]) SHAMapHash{};
|
||||
new (&newChildren[i]) SHAMapTreeNodePtr{};
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
@@ -129,6 +130,16 @@ public:
|
||||
view_->rawDestroyXRP(fee);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies all invariant checkers one by one.
|
||||
*
|
||||
* @param result the result generated by processing this transaction.
|
||||
* @param fee the fee charged for this transaction
|
||||
* @return the result code that should be returned for this transaction.
|
||||
*/
|
||||
TER
|
||||
checkInvariants(TER const result, XRPAmount const fee);
|
||||
|
||||
ApplyViewContext
|
||||
getApplyViewContext()
|
||||
{
|
||||
@@ -139,6 +150,13 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
static TER
|
||||
failInvariantCheck(TER const result);
|
||||
|
||||
template <std::size_t... Is>
|
||||
TER
|
||||
checkInvariantsHelper(TER const result, XRPAmount const fee, std::index_sequence<Is...>);
|
||||
|
||||
OpenView& base_;
|
||||
ApplyFlags flags_;
|
||||
std::optional<ApplyViewImpl> view_;
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include <xrpl/protocol/XRPAmount.h>
|
||||
#include <xrpl/tx/ApplyContext.h>
|
||||
#include <xrpl/tx/applySteps.h>
|
||||
#include <xrpl/tx/invariants/InvariantRunner.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
@@ -148,7 +147,7 @@ struct FeePayer
|
||||
FeePayerType type{FeePayerType::Account};
|
||||
};
|
||||
|
||||
class Transactor : public TxInvariantCheck
|
||||
class Transactor
|
||||
{
|
||||
protected:
|
||||
ApplyContext& ctx_;
|
||||
@@ -159,7 +158,7 @@ protected:
|
||||
XRPAmount preFeeBalance_{}; // Balance before fees.
|
||||
|
||||
public:
|
||||
~Transactor() override = default;
|
||||
virtual ~Transactor() = default;
|
||||
Transactor(Transactor const&) = delete;
|
||||
Transactor&
|
||||
operator=(Transactor const&) = delete;
|
||||
@@ -184,50 +183,20 @@ public:
|
||||
return ctx_.view();
|
||||
}
|
||||
|
||||
/**
|
||||
* Which invariant layers to check.
|
||||
*
|
||||
* Full runs the protocol invariants plus the transaction-specific
|
||||
* check. This is always the scope of the initial pass, even when the
|
||||
* tentative TER is a tec: a bug or exploit could still mutate ledger
|
||||
* state, so transaction-specific invariants must run for failed
|
||||
* transactions too.
|
||||
*
|
||||
* ProtocolOnly runs only the protocol invariants and is used
|
||||
* exclusively for the second invariant pass that follows a
|
||||
* fee-claim reset — specifically, the reset that
|
||||
* Transactor::operator() performs when the initial invariant pass
|
||||
* returns tecINVARIANT_FAILED, rolling the transaction's effects back
|
||||
* to a fee-claim-only state. In that reduced state the
|
||||
* transaction-specific post-conditions no longer apply, but the
|
||||
* protocol invariants must still hold against the fee claim itself.
|
||||
* ProtocolOnly is not intended for other context discards (e.g. the
|
||||
* reset used to handle tecOVERSIZE/tecKILLED/etc. in
|
||||
* processPersistentChanges, or the ctx_.discard() done under
|
||||
* TapFailHard); those paths do not re-run invariants at all.
|
||||
*/
|
||||
enum class InvariantScope { Full, ProtocolOnly };
|
||||
|
||||
/**
|
||||
* Check all invariants for the current transaction.
|
||||
*
|
||||
* Delegates to the free xrpl::checkInvariants runner. When @p scope is
|
||||
* InvariantScope::Full, this transactor is passed so both layers
|
||||
* share a single walk of the modified ledger entries. A failure in
|
||||
* either layer fails the transaction the same way: tecINVARIANT_FAILED
|
||||
* on the first pass, which the caller may respond to by rolling the
|
||||
* transaction back to a fee-claim state and re-invoking this with
|
||||
* InvariantScope::ProtocolOnly; a failure on that post-reset pass
|
||||
* escalates to tefINVARIANT_FAILED.
|
||||
* Runs transaction-specific invariants first (visitInvariantEntry +
|
||||
* finalizeInvariants), then protocol-level invariants. Both layers
|
||||
* always run; the worst failure code is returned.
|
||||
*
|
||||
* @param result the tentative TER from transaction processing.
|
||||
* @param fee the fee consumed by the transaction.
|
||||
* @param scope which invariant layers to check.
|
||||
*
|
||||
* @return the final TER after all invariant checks.
|
||||
*/
|
||||
[[nodiscard]] TER
|
||||
checkInvariants(TER result, XRPAmount fee, InvariantScope scope);
|
||||
checkInvariants(TER result, XRPAmount fee);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/*
|
||||
@@ -569,30 +538,20 @@ private:
|
||||
preflightUniversal(PreflightContext const& ctx);
|
||||
|
||||
/**
|
||||
* Bridges the two-phase TxInvariantCheck interface to this transactor's
|
||||
* visitInvariantEntry/finalizeInvariants hooks. Declared private (rather
|
||||
* than protected, like the hooks they forward to) so that neither this
|
||||
* transactor nor any subclass can call them directly through a
|
||||
* Transactor& — only through the TxInvariantCheck& that the free
|
||||
* xrpl::checkInvariants runner holds, which is where the two-phase
|
||||
* ordering is enforced.
|
||||
* Check transaction-specific invariants only.
|
||||
*
|
||||
* Walks every modified ledger entry via visitInvariantEntry, then
|
||||
* calls finalizeInvariants on the derived transactor. Returns
|
||||
* tecINVARIANT_FAILED if any transaction invariant is violated.
|
||||
*
|
||||
* @param result the tentative TER from transaction processing.
|
||||
* @param fee the fee consumed by the transaction.
|
||||
*
|
||||
* @return the original result if all invariants pass, or
|
||||
* tecINVARIANT_FAILED otherwise.
|
||||
*/
|
||||
void
|
||||
visitEntry(bool isDelete, SLE::const_ref before, SLE::const_ref after) final
|
||||
{
|
||||
visitInvariantEntry(isDelete, before, after);
|
||||
}
|
||||
|
||||
[[nodiscard]] bool
|
||||
finalize(
|
||||
STTx const& tx,
|
||||
TER result,
|
||||
XRPAmount fee,
|
||||
ReadView const& view,
|
||||
beast::Journal const& j) final
|
||||
{
|
||||
return finalizeInvariants(tx, result, fee, view, j);
|
||||
}
|
||||
[[nodiscard]] TER
|
||||
checkTransactionInvariants(TER result, XRPAmount fee);
|
||||
};
|
||||
|
||||
inline bool
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/ledger/helpers/LendingHelpers.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Issue.h>
|
||||
#include <xrpl/protocol/STAmount.h>
|
||||
@@ -12,7 +11,6 @@
|
||||
#include <xrpl/protocol/XRPAmount.h>
|
||||
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
namespace xrpl {
|
||||
@@ -72,8 +70,7 @@ private:
|
||||
STTx const& tx,
|
||||
beast::Journal const& j,
|
||||
bool enforce,
|
||||
bool fixOverrideFreeze,
|
||||
std::optional<LoanDefaultFreezeExemptAccounts> const& loanDefaultAccounts);
|
||||
bool fixOverrideFreeze);
|
||||
|
||||
static bool
|
||||
validateFrozenState(
|
||||
@@ -83,8 +80,7 @@ private:
|
||||
beast::Journal const& j,
|
||||
bool enforce,
|
||||
bool globalFreeze,
|
||||
bool fixOverrideFreeze,
|
||||
std::optional<LoanDefaultFreezeExemptAccounts> const& loanDefaultAccounts);
|
||||
bool fixOverrideFreeze);
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
|
||||
@@ -1,140 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/protocol/XRPAmount.h>
|
||||
#include <xrpl/tx/ApplyContext.h>
|
||||
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
/**
|
||||
* @brief Runtime interface for a transaction-specific invariant check.
|
||||
*
|
||||
* The free checkInvariants runner drives two layers of checks over a single
|
||||
* walk of the modified ledger entries:
|
||||
*
|
||||
* - Protocol checks are the concrete types in InvariantChecks, held in a
|
||||
* std::tuple and dispatched statically by a compile-time fold (no
|
||||
* virtual calls). They are duck-typed against the two-phase contract
|
||||
* described below; see InvariantChecker_PROTOTYPE in InvariantCheck.h.
|
||||
* - The transaction-specific check is injected at runtime through this
|
||||
* interface, so the runner can call it without depending on the concrete
|
||||
* transactor type. Transactor implements this interface directly (see
|
||||
* Transactor.h) so that the interface's access can stay narrower than
|
||||
* Transactor's own public surface: calling through a TxInvariantCheck&
|
||||
* (all the runner ever holds) is public, but calling through a
|
||||
* Transactor& is not, since Transactor overrides these as private
|
||||
* (forwarding to its own protected visitInvariantEntry/finalizeInvariants).
|
||||
*
|
||||
* Both layers honour the same two-phase protocol:
|
||||
*
|
||||
* Phase 1 — state collection (visitEntry). Called once for each ledger
|
||||
* entry created, modified, or deleted by the transaction. Implementations
|
||||
* accumulate whatever state they need to evaluate their post-conditions.
|
||||
* Must not throw.
|
||||
*
|
||||
* Phase 2 — condition evaluation (finalize). Called once after every
|
||||
* modified entry has been visited. Returns true if all post-conditions
|
||||
* hold, false to fail the transaction.
|
||||
*
|
||||
* Rule: invariants must run regardless of transaction result. finalize
|
||||
* MUST perform meaningful checks even when the transaction has failed
|
||||
* (when result is not tesSUCCESS). A bug or exploit could cause a failed
|
||||
* transaction to mutate ledger state in unexpected ways; invariants are the
|
||||
* last line of defense.
|
||||
*
|
||||
* The typical pattern: an invariant that expects a domain-specific state
|
||||
* change (e.g. a Vault being created) should expect that change only when
|
||||
* the transaction succeeded. A failed VaultCreate must not have created a
|
||||
* Vault.
|
||||
*
|
||||
* Rule: privilege-gated checks apply to failed transactions too. Failed
|
||||
* transactions carry no privileges. Any privilege-gated assertion must
|
||||
* therefore also be enforced for failed transactions.
|
||||
*/
|
||||
class TxInvariantCheck
|
||||
{
|
||||
public:
|
||||
virtual ~TxInvariantCheck() = default;
|
||||
|
||||
/**
|
||||
* @brief Called for each ledger entry modified by the transaction.
|
||||
*
|
||||
* @param isDelete true if the SLE is being deleted.
|
||||
* @param before the entry's state before the transaction (nullptr for
|
||||
* newly created entries).
|
||||
* @param after the entry's state after the transaction. For deletions
|
||||
* this is the SLE being erased; use @p isDelete rather than
|
||||
* a null @p after to detect deletions. @p after is
|
||||
* never null.
|
||||
*/
|
||||
virtual void
|
||||
visitEntry(bool isDelete, SLE::const_ref before, SLE::const_ref after) = 0;
|
||||
|
||||
/**
|
||||
* @brief Called after all entries have been visited.
|
||||
*
|
||||
* @param tx the transaction being applied.
|
||||
* @param result the tentative TER result of the transaction.
|
||||
* @param fee the fee consumed by the transaction.
|
||||
* @param view read-only view of the ledger after the transaction.
|
||||
* @param j journal for logging invariant failures.
|
||||
* @return true if all invariants hold; false to fail with
|
||||
* tecINVARIANT_FAILED / tefINVARIANT_FAILED.
|
||||
*/
|
||||
[[nodiscard]] virtual bool
|
||||
finalize(
|
||||
STTx const& tx,
|
||||
TER result,
|
||||
XRPAmount fee,
|
||||
ReadView const& view,
|
||||
beast::Journal const& j) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Run all protocol invariant checks plus the transaction-specific check
|
||||
* in a single pass over the modified entries.
|
||||
*
|
||||
* Both layers share one walk of the modified-entry set: @p txCheck's
|
||||
* visitEntry accumulates state on the same traversal that drives the
|
||||
* protocol checkers, then both layers' finalize run on the complete state.
|
||||
*
|
||||
* Any failure (a finalize returning false or an exception anywhere in the
|
||||
* check) returns failInvariantCheck(result). On the first pass that yields
|
||||
* tecINVARIANT_FAILED, which the transactor treats as a signal to roll the
|
||||
* transaction's effects back to a fee-claim-only state and re-run this
|
||||
* runner against the reduced state (see Transactor::InvariantScope). If
|
||||
* that second pass also fails, the result escalates to tefINVARIANT_FAILED,
|
||||
* which excludes the transaction from the ledger entirely.
|
||||
*
|
||||
* The whole traversal — both layers' visitEntry calls and both layers'
|
||||
* finalize calls — runs under a single try/catch. There is no per-layer
|
||||
* isolation: an exception anywhere aborts the remaining traversal and
|
||||
* finalize calls and fails the transaction.
|
||||
*
|
||||
* @param ctx the apply context for the current transaction.
|
||||
* @param result the tentative TER from transaction processing.
|
||||
* @param fee the fee consumed by the transaction.
|
||||
* @param txCheck the transaction-specific invariant check.
|
||||
* @return the final TER after all invariant checks.
|
||||
*/
|
||||
[[nodiscard]] TER
|
||||
checkInvariants(
|
||||
ApplyContext& ctx,
|
||||
TER result,
|
||||
XRPAmount fee,
|
||||
std::optional<std::reference_wrapper<TxInvariantCheck>> txCheck);
|
||||
|
||||
[[nodiscard]] inline TER
|
||||
checkInvariants(ApplyContext& ctx, TER result, XRPAmount fee)
|
||||
{
|
||||
return checkInvariants(ctx, result, fee, std::nullopt);
|
||||
}
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -1,8 +1,7 @@
|
||||
# check-tools snapshots
|
||||
|
||||
These files capture the output of [`bin/check-tools.sh`](../../bin/check-tools.sh)
|
||||
— the version and resolved store path of each development tool — in each Nix
|
||||
environment:
|
||||
— the versions of the development tooling — in each Nix environment:
|
||||
|
||||
| File | Environment |
|
||||
| ---------------------- | ------------------------------------ |
|
||||
@@ -18,13 +17,9 @@ So if you change the environment (bump the image tag in
|
||||
and commit the affected snapshots.
|
||||
|
||||
Each snapshot is `check-tools.sh` stdout with the git-clone connectivity check
|
||||
skipped (`CHECK_TOOLS_SKIP_CLONE=1`), so it is deterministic for a given
|
||||
environment. On macOS the dev-shell greeting that `nix develop` prints first is
|
||||
dropped with `sed -n '/^Detected OS:/,$p'`.
|
||||
|
||||
The store paths carry their derivation hash, so they change whenever a tool is
|
||||
rebuilt — a `flake.lock` update generally rewrites most of them even when no
|
||||
version moves. That is deliberate: it makes tooling changes visible in review.
|
||||
skipped (`CHECK_TOOLS_SKIP_CLONE=1`), so it contains only deterministic version
|
||||
data. On macOS the dev-shell greeting that `nix develop` prints first is dropped
|
||||
with `sed -n '/^Detected OS:/,$p'`.
|
||||
|
||||
## Regenerating
|
||||
|
||||
|
||||
@@ -1,143 +1,47 @@
|
||||
Detected OS: macos (Darwin arm64)
|
||||
|
||||
Core build tools:
|
||||
✅ cmake
|
||||
cmake version 4.1.2
|
||||
/nix/store/gvabsb4yqb5xsqzqph54rijnn4zpihnp-cmake-4.1.2/bin/cmake
|
||||
✅ conan
|
||||
Conan version 2.28.1
|
||||
/nix/store/9jiyxmkpwmn6dcqs0765s83riw3l5ail-conan-2.28.1/bin/conan
|
||||
✅ git
|
||||
git version 2.54.0
|
||||
/nix/store/a14yxcqvv9x2l9mllgpirzhvz93pgprg-git-2.54.0/bin/git
|
||||
✅ python3
|
||||
Python 3.13.13
|
||||
/nix/store/ygxqin6ydzjfawywqpp5pal8wv6sf5bh-python3-3.13.13/bin/python3.13
|
||||
[ ok ] cmake cmake version 4.1.2
|
||||
[ ok ] conan Conan version 2.28.1
|
||||
[ ok ] git git version 2.54.0
|
||||
[ ok ] python3 Python 3.13.13
|
||||
|
||||
Development tooling:
|
||||
✅ ccache
|
||||
ccache version 4.13.6
|
||||
/nix/store/57davyvs6p6dkrl3svzwg1ph18wsy4cz-ccache-4.13.6/bin/ccache
|
||||
✅ clang
|
||||
clang version 22.1.7
|
||||
/nix/store/192glrb2cldvziyf3378mzjqbzx3ih4g-clang-wrapper-22.1.7/bin/clang
|
||||
✅ clang-22
|
||||
clang version 22.1.7
|
||||
/nix/store/rbap7zqq7mw00fyqa02p5rj7gqjp4w5i-clang-22/bin/clang-22
|
||||
✅ clang++
|
||||
clang version 22.1.7
|
||||
/nix/store/192glrb2cldvziyf3378mzjqbzx3ih4g-clang-wrapper-22.1.7/bin/clang++
|
||||
✅ clang++-22
|
||||
clang version 22.1.7
|
||||
/nix/store/v9haf787f7bcz0mq1sad4bpyx21pj6li-clang++-22/bin/clang++-22
|
||||
✅ ClangBuildAnalyzer
|
||||
ClangBuildAnalyzer 1.6.0
|
||||
/nix/store/4l50ds9fa2mkvh7wg8qzrlbmjs12sb8l-clangbuildanalyzer-1.6.0/bin/ClangBuildAnalyzer
|
||||
✅ curl
|
||||
curl 8.20.0 (aarch64-apple-darwin25.3.0) libcurl/8.20.0 OpenSSL/3.6.2 zlib/1.3.2 libssh2/1.11.1 nghttp2/1.69.0 mit-krb5/1.22.1
|
||||
/nix/store/kclq0czaxvsgh4ym9ld7b6iwy50l1snk-curl-8.20.0-bin/bin/curl
|
||||
✅ file
|
||||
file-5.47
|
||||
/nix/store/dax63li7wwcbqxxkkgzc4g2rx7d4w86x-file-5.47/bin/file
|
||||
✅ less
|
||||
less 692 (PCRE2 regular expressions)
|
||||
/nix/store/lvr16y75r1pdxpdv0aph5ak2yd0hkvqm-less-692/bin/less
|
||||
✅ make
|
||||
GNU Make 4.4.1
|
||||
/nix/store/8wwiw8pwyhrkzyq28hqzxfl4z84lks81-gnumake-4.4.1/bin/make
|
||||
✅ netstat
|
||||
present
|
||||
/nix/store/qsd1kzqb0ahrk433vmyl245gp623j19s-network_cmds-730.80.3/bin/netstat
|
||||
✅ ninja
|
||||
1.13.2
|
||||
/nix/store/bqykhrblarkj4fl0hz2mf8ngwfv6x6bz-ninja-1.13.2/bin/ninja
|
||||
✅ perl
|
||||
v5.42.0
|
||||
/nix/store/js13ri9fvm0ajk1fpd3acigys2a9whdv-perl-5.42.0/bin/perl
|
||||
✅ pkg-config
|
||||
0.29.2
|
||||
/nix/store/lzrwr375jqhhbca116kja96xf1md83l8-pkg-config-wrapper-0.29.2/bin/pkg-config
|
||||
✅ vim
|
||||
VIM - Vi IMproved 9.2 (2026 Feb 14, compiled Jan 01 1980 00:00:00)
|
||||
/nix/store/6vbkykg92w603c0sw3mkk7p7mfaawbns-vim-9.2.0389/bin/vim
|
||||
✅ zip
|
||||
Zip 3.0
|
||||
/nix/store/z6ph729vcakbvz3wh8ln1wk6mi06w487-zip-3.0/bin/zip
|
||||
✅ clang-apply-replacements
|
||||
clang-apply-replacements version 22.1.7
|
||||
/nix/store/vzyyjf3cm1hbj9wcr2qcb66x6j98zpy7-clang-tools-22.1.7/bin/clang-apply-replacements
|
||||
✅ clang-apply-replacements-22
|
||||
clang-apply-replacements version 22.1.7
|
||||
/nix/store/m3ii69rca4077lf4wlk7m3jcag1fs577-clang-apply-replacements-22/bin/clang-apply-replacements-22
|
||||
✅ clang-format
|
||||
clang-format version 22.1.7
|
||||
/nix/store/vzyyjf3cm1hbj9wcr2qcb66x6j98zpy7-clang-tools-22.1.7/bin/clang-format
|
||||
✅ clang-format-22
|
||||
clang-format version 22.1.7
|
||||
/nix/store/4fawqy6ngqcsqd2ygyyzm93q0xy3f5gs-clang-format-22/bin/clang-format-22
|
||||
✅ clang-tidy
|
||||
LLVM version 22.1.7
|
||||
/nix/store/vzyyjf3cm1hbj9wcr2qcb66x6j98zpy7-clang-tools-22.1.7/bin/clang-tidy
|
||||
✅ clang-tidy-22
|
||||
LLVM version 22.1.7
|
||||
/nix/store/jqw4280saixaxxihwdba9ldm2fsm6dr3-clang-tidy-22/bin/clang-tidy-22
|
||||
✅ dot
|
||||
dot - graphviz version 12.2.1 (0)
|
||||
/nix/store/ijb4fbnqa6wzlpqnhb6q9knqpf7qqn5z-graphviz-12.2.1/bin/dot
|
||||
✅ doxygen
|
||||
1.16.1
|
||||
/nix/store/kbryjdpq9jizjb0ws0nzbf2h2ymbdiwm-doxygen-1.16.1/bin/doxygen
|
||||
✅ gcovr
|
||||
gcovr 8.4
|
||||
/nix/store/wn8jiyh9p0bybs96s4163qp3k8vfmczx-python3.13-gcovr-8.4/bin/gcovr
|
||||
✅ gh
|
||||
gh version 2.94.0 (nixpkgs)
|
||||
/nix/store/fhnpw0hs0gjms1ha6ap02jq7rx13gkbp-gh-2.94.0/bin/gh
|
||||
✅ git-cliff
|
||||
git-cliff 2.13.1
|
||||
/nix/store/cy0wwhgxa7yvrz97zydbq6sqmixc90fq-git-cliff-2.13.1/bin/git-cliff
|
||||
✅ git-lfs
|
||||
git-lfs/3.7.1 (3.7.1; darwin arm64; go 1.26.3)
|
||||
/nix/store/k9r7zjfjplqa4d5s71cqvf2iv73jd9mc-git-lfs-3.7.1/bin/git-lfs
|
||||
✅ gpg
|
||||
gpg (GnuPG) 2.4.9
|
||||
/nix/store/cgh6iwzz5jgx9z5whka4vgj210i6npc6-gnupg-2.4.9/bin/gpg
|
||||
✅ pre-commit
|
||||
pre-commit 4.5.1
|
||||
/nix/store/z3cca68620w0w10f090szgzdnmh1waf2-pre-commit-4.5.1/bin/pre-commit
|
||||
✅ run-clang-tidy
|
||||
usage: run-clang-tidy [-h] [-allow-enabling-alpha-checkers]
|
||||
/nix/store/4x28x911z2f9y7adqlh3qspp4a16dig7-run-clang-tidy/bin/run-clang-tidy
|
||||
✅ run-clang-tidy-22
|
||||
usage: run-clang-tidy [-h] [-allow-enabling-alpha-checkers]
|
||||
/nix/store/x8iymrh76sk5q91ryg5pa7i32s6gfh34-run-clang-tidy-22/bin/run-clang-tidy-22
|
||||
[ ok ] ccache ccache version 4.13.6
|
||||
[ ok ] clang clang version 22.1.7
|
||||
[ ok ] clang++ clang version 22.1.7
|
||||
[ ok ] ClangBuildAnalyzer ClangBuildAnalyzer 1.6.0
|
||||
[ ok ] curl curl 8.20.0 (aarch64-apple-darwin25.3.0) libcurl/8.20.0 OpenSSL/3.6.2 zlib/1.3.2 libssh2/1.11.1 nghttp2/1.69.0 mit-krb5/1.22.1
|
||||
[ ok ] file file-5.47
|
||||
[ ok ] less less 692 (PCRE2 regular expressions)
|
||||
[ ok ] make GNU Make 4.4.1
|
||||
[ ok ] netstat present
|
||||
[ ok ] ninja 1.13.2
|
||||
[ ok ] perl v5.42.0
|
||||
[ ok ] pkg-config 0.29.2
|
||||
[ ok ] vim VIM - Vi IMproved 9.2 (2026 Feb 14, compiled Jan 01 1980 00:00:00)
|
||||
[ ok ] zip Zip 3.0
|
||||
[ ok ] clang-format clang-format version 22.1.7
|
||||
[ ok ] dot dot - graphviz version 12.2.1 (0)
|
||||
[ ok ] doxygen 1.16.1
|
||||
[ ok ] gcovr gcovr 8.4
|
||||
[ ok ] gh gh version 2.94.0 (nixpkgs)
|
||||
[ ok ] git-cliff git-cliff 2.13.1
|
||||
[ ok ] git-lfs git-lfs/3.7.1 (3.7.1; darwin arm64; go 1.26.3)
|
||||
[ ok ] gpg gpg (GnuPG) 2.4.9
|
||||
[ ok ] pre-commit pre-commit 4.5.1
|
||||
[ ok ] run-clang-tidy usage: run-clang-tidy [-h] [-allow-enabling-alpha-checkers]
|
||||
|
||||
Rust toolchain:
|
||||
✅ cargo
|
||||
cargo 1.95.0 (f2d3ce0bd 2026-03-21)
|
||||
/nix/store/92vz1f4kislnj58j1pr1788l688py6f0-rust-minimal-1.95.0/bin/cargo
|
||||
✅ cargo-audit
|
||||
cargo-audit-audit 0.22.1
|
||||
/nix/store/snwkga2f5gyf404h7mmp9wriwxb8v65f-cargo-audit-0.22.1/bin/cargo-audit
|
||||
✅ cargo-llvm-cov
|
||||
cargo-llvm-cov 0.8.5
|
||||
/nix/store/fpiqdh91gwyxalqp409ynm0s0g086w7w-cargo-llvm-cov-0.8.5/bin/cargo-llvm-cov
|
||||
✅ cargo-nextest
|
||||
cargo-nextest 0.9.137
|
||||
/nix/store/ylz7m947mhkgsp6i7611id3s3gcd58nq-cargo-nextest-0.9.137/bin/cargo-nextest
|
||||
✅ clippy-driver
|
||||
clippy 0.1.95 (59807616e1 2026-04-14)
|
||||
/nix/store/92vz1f4kislnj58j1pr1788l688py6f0-rust-minimal-1.95.0/bin/clippy-driver
|
||||
✅ rust-analyzer
|
||||
rust-analyzer 1.95.0 (59807616 2026-04-14)
|
||||
/nix/store/jqvjap2727r9cjpr25fkw5glv2kbxrdx-rust-analyzer-preview-1.95.0-aarch64-apple-darwin/bin/rust-analyzer
|
||||
✅ rustc
|
||||
rustc 1.95.0 (59807616e 2026-04-14)
|
||||
/nix/store/92vz1f4kislnj58j1pr1788l688py6f0-rust-minimal-1.95.0/bin/rustc
|
||||
✅ rustfmt
|
||||
rustfmt 1.9.0-stable (59807616e1 2026-04-14)
|
||||
/nix/store/03x750yj6fakl7shbhicpnkxiwqxjrrs-rustfmt-preview-1.95.0-aarch64-apple-darwin/bin/rustfmt
|
||||
[ ok ] cargo cargo 1.95.0 (f2d3ce0bd 2026-03-21)
|
||||
[ ok ] cargo-audit cargo-audit-audit 0.22.1
|
||||
[ ok ] cargo-llvm-cov cargo-llvm-cov 0.8.5
|
||||
[ ok ] cargo-nextest cargo-nextest 0.9.137
|
||||
[ ok ] clippy clippy 0.1.95 (59807616e1 2026-04-14)
|
||||
[ ok ] rust-analyzer rust-analyzer 1.95.0 (59807616 2026-04-14)
|
||||
[ ok ] rustc rustc 1.95.0 (59807616e 2026-04-14)
|
||||
[ ok ] rustfmt rustfmt 1.9.0-stable (59807616e1 2026-04-14)
|
||||
|
||||
Skipping git-over-HTTPS check (CHECK_TOOLS_SKIP_CLONE is set).
|
||||
|
||||
✅ All 44 checked tools are present and runnable.
|
||||
All 36 checked tools are present and runnable.
|
||||
|
||||
@@ -1,171 +1,55 @@
|
||||
Detected OS: linux (Linux x86_64)
|
||||
|
||||
Core build tools:
|
||||
✅ cmake
|
||||
cmake version 4.1.2
|
||||
/nix/store/r9941n32g4wyvggz2703dlplbdq8a6rd-cmake-4.1.2/bin/cmake
|
||||
✅ conan
|
||||
Conan version 2.28.1
|
||||
/nix/store/lxny9y4jvjdws7hgz1mygvb7hjrpmna5-conan-2.28.1/bin/conan
|
||||
✅ git
|
||||
git version 2.54.0
|
||||
/nix/store/bcnisk3ydfgv26v2gw3zlky24g00yww2-git-2.54.0/bin/git
|
||||
✅ python3
|
||||
Python 3.13.13
|
||||
/nix/store/60m4rxhg2fldqaak400c0lry96ijrzqn-python3-3.13.13/bin/python3.13
|
||||
[ ok ] cmake cmake version 4.1.2
|
||||
[ ok ] conan Conan version 2.28.1
|
||||
[ ok ] git git version 2.54.0
|
||||
[ ok ] python3 Python 3.13.13
|
||||
|
||||
Development tooling:
|
||||
✅ ccache
|
||||
ccache version 4.13.6
|
||||
/nix/store/c9wwl7s5i6rsfwvf4v0xbbmzx5m6jgfr-ccache-4.13.6/bin/ccache
|
||||
✅ clang
|
||||
clang version 22.1.7
|
||||
/nix/store/ff0hrp9r9i3pa5arkdw0sgmzp8d576qi-clang-wrapper-22.1.7/bin/clang
|
||||
✅ clang-22
|
||||
clang version 22.1.7
|
||||
/nix/store/dagc2rq44gfbr7w7yvvqca3yqpc9gqbq-clang-22/bin/clang-22
|
||||
✅ clang++
|
||||
clang version 22.1.7
|
||||
/nix/store/ff0hrp9r9i3pa5arkdw0sgmzp8d576qi-clang-wrapper-22.1.7/bin/clang++
|
||||
✅ clang++-22
|
||||
clang version 22.1.7
|
||||
/nix/store/l5m8clin1npl605wdkd8mr18ggxww3z4-clang++-22/bin/clang++-22
|
||||
✅ ClangBuildAnalyzer
|
||||
ClangBuildAnalyzer 1.6.0
|
||||
/nix/store/bshlmn8fqw55nsnm581xqlfbahfkykxx-clangbuildanalyzer-1.6.0/bin/ClangBuildAnalyzer
|
||||
✅ curl
|
||||
curl 8.20.0 (x86_64-pc-linux-gnu) libcurl/8.20.0 OpenSSL/3.6.2 zlib/1.3.2 libssh2/1.11.1 nghttp2/1.69.0 mit-krb5/1.22.1
|
||||
/nix/store/zbwymrp4lcfjc4kkk0n4779v0kjjz58z-curl-8.20.0-bin/bin/curl
|
||||
✅ file
|
||||
file-5.47
|
||||
/nix/store/bizyfqdw0h67wzqmp10knmf9s2pqahdb-file-5.47/bin/file
|
||||
✅ less
|
||||
less 692 (PCRE2 regular expressions)
|
||||
/nix/store/c6bacbn93qg4a7g9n4czww8rg24dvysr-less-692/bin/less
|
||||
✅ make
|
||||
GNU Make 4.4.1
|
||||
/nix/store/d3bwqm6bymhy3pdgbvf7vxjqfp31m3j1-gnumake-4.4.1/bin/make
|
||||
✅ netstat
|
||||
net-tools 2.10
|
||||
/nix/store/jmyzqvgflnswmws7rnxx6g3zbj680xvd-net-tools-2.10/bin/netstat
|
||||
✅ ninja
|
||||
1.13.2
|
||||
/nix/store/7a235m7crqbb4h49sak20fqxpw3n7hr0-ninja-1.13.2/bin/ninja
|
||||
✅ perl
|
||||
v5.42.0
|
||||
/nix/store/6plwsm6pkq79yjv4xvy8csk2pd4hzr67-perl-5.42.0/bin/perl
|
||||
✅ pkg-config
|
||||
0.29.2
|
||||
/nix/store/1m05k7xgfnw6jc21xxk5681ni3ar97wf-pkg-config-wrapper-0.29.2/bin/pkg-config
|
||||
✅ vim
|
||||
VIM - Vi IMproved 9.2 (2026 Feb 14, compiled Jan 01 1980 00:00:00)
|
||||
/nix/store/hvyqx52g4g2fxhgpans3fksjj6lmlyaw-vim-9.2.0389/bin/vim
|
||||
✅ zip
|
||||
Zip 3.0
|
||||
/nix/store/qnd2ag67hrjj0b6vbmisdshf50r6s72n-zip-3.0/bin/zip
|
||||
✅ clang-apply-replacements
|
||||
clang-apply-replacements version 22.1.7
|
||||
/nix/store/4zp1rjpj2xijrv4kqpwsy3ixwb2r6nlk-clang-tools-22.1.7/bin/clang-apply-replacements
|
||||
✅ clang-apply-replacements-22
|
||||
clang-apply-replacements version 22.1.7
|
||||
/nix/store/py2wihg0a96qcppv4hjmww547xabr0fb-clang-apply-replacements-22/bin/clang-apply-replacements-22
|
||||
✅ clang-format
|
||||
clang-format version 22.1.7
|
||||
/nix/store/4zp1rjpj2xijrv4kqpwsy3ixwb2r6nlk-clang-tools-22.1.7/bin/clang-format
|
||||
✅ clang-format-22
|
||||
clang-format version 22.1.7
|
||||
/nix/store/kz820ccifjlwqnwqjsx7kbiajrgsmbrh-clang-format-22/bin/clang-format-22
|
||||
✅ clang-tidy
|
||||
LLVM version 22.1.7
|
||||
/nix/store/4zp1rjpj2xijrv4kqpwsy3ixwb2r6nlk-clang-tools-22.1.7/bin/clang-tidy
|
||||
✅ clang-tidy-22
|
||||
LLVM version 22.1.7
|
||||
/nix/store/gdrkvpw846lkyzh8y9p3zx50g6ml2v84-clang-tidy-22/bin/clang-tidy-22
|
||||
✅ dot
|
||||
dot - graphviz version 12.2.1 (0)
|
||||
/nix/store/12rgns2296s4qcja778gvcbx61z77rc4-graphviz-12.2.1/bin/dot
|
||||
✅ doxygen
|
||||
1.16.1
|
||||
/nix/store/k0vzr5lvgq1byraknzwvk51wcgpnsrkh-doxygen-1.16.1/bin/doxygen
|
||||
✅ gcovr
|
||||
gcovr 8.4
|
||||
/nix/store/iyzi7fpyclqrha054adnizvif02lg49x-python3.13-gcovr-8.4/bin/gcovr
|
||||
✅ gh
|
||||
gh version 2.94.0 (nixpkgs)
|
||||
/nix/store/pidh15szlsb1vc41xdsa3xbdghdazvby-gh-2.94.0/bin/gh
|
||||
✅ git-cliff
|
||||
git-cliff 2.13.1
|
||||
/nix/store/1q851fs62shgjhc03fxxdkpzxdjg7k11-git-cliff-2.13.1/bin/git-cliff
|
||||
✅ git-lfs
|
||||
git-lfs/3.7.1 (3.7.1; linux amd64; go 1.26.3)
|
||||
/nix/store/6ljwpal7b1756708m33vj0crpral7mvl-git-lfs-3.7.1/bin/git-lfs
|
||||
✅ gpg
|
||||
gpg (GnuPG) 2.4.9
|
||||
/nix/store/wx7vk8babxkgy813r70yc67vcwnmagbx-gnupg-2.4.9/bin/gpg
|
||||
✅ pre-commit
|
||||
pre-commit 4.5.1
|
||||
/nix/store/bj6i9vl34cij5h0r165y40hrjqak0bmz-pre-commit-4.5.1/bin/pre-commit
|
||||
✅ run-clang-tidy
|
||||
usage: run-clang-tidy [-h] [-allow-enabling-alpha-checkers]
|
||||
/nix/store/sbg911hs9dbclrzlp04br3iyfpgnaj6r-run-clang-tidy/bin/run-clang-tidy
|
||||
✅ run-clang-tidy-22
|
||||
usage: run-clang-tidy [-h] [-allow-enabling-alpha-checkers]
|
||||
/nix/store/n8yak1ap308gvi7gmrniw0ybsx80fjws-run-clang-tidy-22/bin/run-clang-tidy-22
|
||||
[ ok ] ccache ccache version 4.13.6
|
||||
[ ok ] clang clang version 22.1.7
|
||||
[ ok ] clang++ clang version 22.1.7
|
||||
[ ok ] ClangBuildAnalyzer ClangBuildAnalyzer 1.6.0
|
||||
[ ok ] curl curl 8.20.0 (x86_64-pc-linux-gnu) libcurl/8.20.0 OpenSSL/3.6.2 zlib/1.3.2 libssh2/1.11.1 nghttp2/1.69.0 mit-krb5/1.22.1
|
||||
[ ok ] file file-5.47
|
||||
[ ok ] less less 692 (PCRE2 regular expressions)
|
||||
[ ok ] make GNU Make 4.4.1
|
||||
[ ok ] netstat net-tools 2.10
|
||||
[ ok ] ninja 1.13.2
|
||||
[ ok ] perl v5.42.0
|
||||
[ ok ] pkg-config 0.29.2
|
||||
[ ok ] vim VIM - Vi IMproved 9.2 (2026 Feb 14, compiled Jan 01 1980 00:00:00)
|
||||
[ ok ] zip Zip 3.0
|
||||
[ ok ] clang-format clang-format version 22.1.7
|
||||
[ ok ] dot dot - graphviz version 12.2.1 (0)
|
||||
[ ok ] doxygen 1.16.1
|
||||
[ ok ] gcovr gcovr 8.4
|
||||
[ ok ] gh gh version 2.94.0 (nixpkgs)
|
||||
[ ok ] git-cliff git-cliff 2.13.1
|
||||
[ ok ] git-lfs git-lfs/3.7.1 (3.7.1; linux amd64; go 1.26.3)
|
||||
[ ok ] gpg gpg (GnuPG) 2.4.9
|
||||
[ ok ] pre-commit pre-commit 4.5.1
|
||||
[ ok ] run-clang-tidy usage: run-clang-tidy [-h] [-allow-enabling-alpha-checkers]
|
||||
|
||||
Rust toolchain:
|
||||
✅ cargo
|
||||
cargo 1.95.0 (f2d3ce0bd 2026-03-21)
|
||||
/nix/store/85qbwr3vzfs58m7ywnjblz105p8ahbrv-cargo-1.95.0-x86_64-unknown-linux-gnu/bin/cargo
|
||||
✅ cargo-audit
|
||||
cargo-audit-audit 0.22.1
|
||||
/nix/store/2w9if868piw98xz057sz97jnjvf7hnvf-cargo-audit-0.22.1/bin/cargo-audit
|
||||
✅ cargo-llvm-cov
|
||||
cargo-llvm-cov 0.8.5
|
||||
/nix/store/jjpdf1l6izz6607a346ykra9sndzaw7h-cargo-llvm-cov-0.8.5/bin/cargo-llvm-cov
|
||||
✅ cargo-nextest
|
||||
cargo-nextest 0.9.137
|
||||
/nix/store/jhkr7gwyrchkml33gyns9cy0yn7b57qc-cargo-nextest-0.9.137/bin/cargo-nextest
|
||||
✅ clippy-driver
|
||||
clippy 0.1.95 (59807616e1 2026-04-14)
|
||||
/nix/store/bnvg9nmdq4g98dd9v3r6nvjg5h2rr8i7-rust-minimal-1.95.0/bin/clippy-driver
|
||||
✅ rust-analyzer
|
||||
rust-analyzer 1.95.0 (5980761 2026-04-14)
|
||||
/nix/store/i3cnpngfwa3k4jn431pl6ji1r4qmxky9-rust-analyzer-preview-1.95.0-x86_64-unknown-linux-gnu/bin/rust-analyzer
|
||||
✅ rustc
|
||||
rustc 1.95.0 (59807616e 2026-04-14)
|
||||
/nix/store/bnvg9nmdq4g98dd9v3r6nvjg5h2rr8i7-rust-minimal-1.95.0/bin/rustc
|
||||
✅ rustfmt
|
||||
rustfmt 1.9.0-stable (59807616e1 2026-04-14)
|
||||
/nix/store/366hhk2dgwxmnf4hgrj4b8llhjr3hf0i-rustfmt-preview-1.95.0-x86_64-unknown-linux-gnu/bin/rustfmt
|
||||
[ ok ] cargo cargo 1.95.0 (f2d3ce0bd 2026-03-21)
|
||||
[ ok ] cargo-audit cargo-audit-audit 0.22.1
|
||||
[ ok ] cargo-llvm-cov cargo-llvm-cov 0.8.5
|
||||
[ ok ] cargo-nextest cargo-nextest 0.9.137
|
||||
[ ok ] clippy clippy 0.1.95 (59807616e1 2026-04-14)
|
||||
[ ok ] rust-analyzer rust-analyzer 1.95.0 (5980761 2026-04-14)
|
||||
[ ok ] rustc rustc 1.95.0 (59807616e 2026-04-14)
|
||||
[ ok ] rustfmt rustfmt 1.9.0-stable (59807616e1 2026-04-14)
|
||||
|
||||
GCC toolchain:
|
||||
✅ gcc
|
||||
gcc (GCC) 15.2.0
|
||||
/nix/store/3dd6y3pq00i3r85l45jvz63wjya403nl-gcc-wrapper-15.2.0/bin/gcc
|
||||
✅ gcc-15
|
||||
gcc (GCC) 15.2.0
|
||||
/nix/store/d6iri2s6bzqq5ac3fg25j6hgnn1lz44f-gcc-15/bin/gcc-15
|
||||
✅ g++
|
||||
g++ (GCC) 15.2.0
|
||||
/nix/store/3dd6y3pq00i3r85l45jvz63wjya403nl-gcc-wrapper-15.2.0/bin/g++
|
||||
✅ g++-15
|
||||
g++ (GCC) 15.2.0
|
||||
/nix/store/gm3msmmxq055lm9gprkfjj9d2gdz1mpg-g++-15/bin/g++-15
|
||||
✅ cpp
|
||||
cpp (GCC) 15.2.0
|
||||
/nix/store/3dd6y3pq00i3r85l45jvz63wjya403nl-gcc-wrapper-15.2.0/bin/cpp
|
||||
✅ cpp-15
|
||||
cpp (GCC) 15.2.0
|
||||
/nix/store/bn3gmn0m7g4gn2i0yml46fljc7mghiq5-cpp-15/bin/cpp-15
|
||||
✅ gcov
|
||||
gcov (GCC) 15.2.0
|
||||
/nix/store/xvv5sm5i8x0ks6ypfkzl7c4j9srnxz7k-gcc-15.2.0/bin/gcov
|
||||
[ ok ] gcc gcc (GCC) 15.2.0
|
||||
[ ok ] g++ g++ (GCC) 15.2.0
|
||||
[ ok ] gcov gcov (GCC) 15.2.0
|
||||
|
||||
Mold:
|
||||
✅ mold
|
||||
mold 2.41.0 (compatible with GNU ld)
|
||||
/nix/store/2w6fpgxjzzyqmd25wzplm23dfa49a0p2-mold-unwrapped-wrapper-2.41.0/bin/mold
|
||||
[ ok ] mold mold 2.41.0 (compatible with GNU ld)
|
||||
|
||||
Skipping git-over-HTTPS check (CHECK_TOOLS_SKIP_CLONE is set).
|
||||
|
||||
✅ All 52 checked tools are present and runnable.
|
||||
All 40 checked tools are present and runnable.
|
||||
|
||||
@@ -1,171 +1,55 @@
|
||||
Detected OS: linux (Linux aarch64)
|
||||
|
||||
Core build tools:
|
||||
✅ cmake
|
||||
cmake version 4.1.2
|
||||
/nix/store/nkcpxjifkambzlrwh27a8igvhnbchibg-cmake-4.1.2/bin/cmake
|
||||
✅ conan
|
||||
Conan version 2.28.1
|
||||
/nix/store/8i2gyqgc00xvxg9xm6y7n0ilncdv8imw-conan-2.28.1/bin/conan
|
||||
✅ git
|
||||
git version 2.54.0
|
||||
/nix/store/ixp98f9avf8ikpdrmp40cj33g0dazyp9-git-2.54.0/bin/git
|
||||
✅ python3
|
||||
Python 3.13.13
|
||||
/nix/store/lqn6mbgzzdrqq2qkwddcmxj9z6amdd86-python3-3.13.13/bin/python3.13
|
||||
[ ok ] cmake cmake version 4.1.2
|
||||
[ ok ] conan Conan version 2.28.1
|
||||
[ ok ] git git version 2.54.0
|
||||
[ ok ] python3 Python 3.13.13
|
||||
|
||||
Development tooling:
|
||||
✅ ccache
|
||||
ccache version 4.13.6
|
||||
/nix/store/2q39xi2kbi04ibga7635f2sl148d1mzv-ccache-4.13.6/bin/ccache
|
||||
✅ clang
|
||||
clang version 22.1.7
|
||||
/nix/store/xjqffrq9i7la058s9865ig71l9sp1ys5-clang-wrapper-22.1.7/bin/clang
|
||||
✅ clang-22
|
||||
clang version 22.1.7
|
||||
/nix/store/vcf6ilfwn57828hwzyp6zlyr24j9j6yw-clang-22/bin/clang-22
|
||||
✅ clang++
|
||||
clang version 22.1.7
|
||||
/nix/store/xjqffrq9i7la058s9865ig71l9sp1ys5-clang-wrapper-22.1.7/bin/clang++
|
||||
✅ clang++-22
|
||||
clang version 22.1.7
|
||||
/nix/store/xby0f6gamr7m27zp5cndsvghbp9lgb3c-clang++-22/bin/clang++-22
|
||||
✅ ClangBuildAnalyzer
|
||||
ClangBuildAnalyzer 1.6.0
|
||||
/nix/store/h893hd4q1bb6ily2lby5dzyfrrzd2nvj-clangbuildanalyzer-1.6.0/bin/ClangBuildAnalyzer
|
||||
✅ curl
|
||||
curl 8.20.0 (aarch64-unknown-linux-gnu) libcurl/8.20.0 OpenSSL/3.6.2 zlib/1.3.2 libssh2/1.11.1 nghttp2/1.69.0 mit-krb5/1.22.1
|
||||
/nix/store/i1s0lqwlrmjd2dxzgy2p84cxqqsb0bmk-curl-8.20.0-bin/bin/curl
|
||||
✅ file
|
||||
file-5.47
|
||||
/nix/store/dx973zg9km2w9albsib2vw9wyvacfrlw-file-5.47/bin/file
|
||||
✅ less
|
||||
less 692 (PCRE2 regular expressions)
|
||||
/nix/store/1blb3s7hhsr77wqi598m6k1qkfp3ms0w-less-692/bin/less
|
||||
✅ make
|
||||
GNU Make 4.4.1
|
||||
/nix/store/9ngw1ippk25jjj5fjxv36xbp6iq7rxdx-gnumake-4.4.1/bin/make
|
||||
✅ netstat
|
||||
net-tools 2.10
|
||||
/nix/store/7vdsz21f0s499s5yyqzp5s4676q4yxdd-net-tools-2.10/bin/netstat
|
||||
✅ ninja
|
||||
1.13.2
|
||||
/nix/store/8ksx98gsbn5lmlizcmw57yd4sg0k2p58-ninja-1.13.2/bin/ninja
|
||||
✅ perl
|
||||
v5.42.0
|
||||
/nix/store/5wnly69vv1i3y97al4v3xrqymf9hlzgq-perl-5.42.0/bin/perl
|
||||
✅ pkg-config
|
||||
0.29.2
|
||||
/nix/store/c7vwy0gl1q0agl2h22gi0m9dg7xxad2l-pkg-config-wrapper-0.29.2/bin/pkg-config
|
||||
✅ vim
|
||||
VIM - Vi IMproved 9.2 (2026 Feb 14, compiled Jan 01 1980 00:00:00)
|
||||
/nix/store/v8c7pvx26irvy9k5sbwd183cyvckzzb3-vim-9.2.0389/bin/vim
|
||||
✅ zip
|
||||
Zip 3.0
|
||||
/nix/store/5mh19mvbv9ym2sm9vymyyaac5l2cj2jq-zip-3.0/bin/zip
|
||||
✅ clang-apply-replacements
|
||||
clang-apply-replacements version 22.1.7
|
||||
/nix/store/s53p2m776iqaz7acgr5csgpsd18w15h7-clang-tools-22.1.7/bin/clang-apply-replacements
|
||||
✅ clang-apply-replacements-22
|
||||
clang-apply-replacements version 22.1.7
|
||||
/nix/store/bg4kn8z81hk7b9284rjqvr51wpfjqc24-clang-apply-replacements-22/bin/clang-apply-replacements-22
|
||||
✅ clang-format
|
||||
clang-format version 22.1.7
|
||||
/nix/store/s53p2m776iqaz7acgr5csgpsd18w15h7-clang-tools-22.1.7/bin/clang-format
|
||||
✅ clang-format-22
|
||||
clang-format version 22.1.7
|
||||
/nix/store/79v57mzcw8ng8kl7p961ck08ymhp31v7-clang-format-22/bin/clang-format-22
|
||||
✅ clang-tidy
|
||||
LLVM version 22.1.7
|
||||
/nix/store/s53p2m776iqaz7acgr5csgpsd18w15h7-clang-tools-22.1.7/bin/clang-tidy
|
||||
✅ clang-tidy-22
|
||||
LLVM version 22.1.7
|
||||
/nix/store/wdyd6cb9z1lyi37lbzvwldgcc7yv1n5c-clang-tidy-22/bin/clang-tidy-22
|
||||
✅ dot
|
||||
dot - graphviz version 12.2.1 (0)
|
||||
/nix/store/58rrk4yzwpmyxvl8cqm18h3dhv24zf00-graphviz-12.2.1/bin/dot
|
||||
✅ doxygen
|
||||
1.16.1
|
||||
/nix/store/hq32kzwpl89wgr49iq0gmqn9r5n072zq-doxygen-1.16.1/bin/doxygen
|
||||
✅ gcovr
|
||||
gcovr 8.4
|
||||
/nix/store/sml3xbbfhhlhk6h7jnlg19pdbx9b764b-python3.13-gcovr-8.4/bin/gcovr
|
||||
✅ gh
|
||||
gh version 2.94.0 (nixpkgs)
|
||||
/nix/store/7hh2qi0gj2ifbxbl56cjzbiyfc379bji-gh-2.94.0/bin/gh
|
||||
✅ git-cliff
|
||||
git-cliff 2.13.1
|
||||
/nix/store/bidn3pz53yd6qlg711917xx0q10hqmqv-git-cliff-2.13.1/bin/git-cliff
|
||||
✅ git-lfs
|
||||
git-lfs/3.7.1 (3.7.1; linux arm64; go 1.26.3)
|
||||
/nix/store/4rsklvkbac5bayy0zv12kxyvspi4sshd-git-lfs-3.7.1/bin/git-lfs
|
||||
✅ gpg
|
||||
gpg (GnuPG) 2.4.9
|
||||
/nix/store/ka4i8zz5ni3rzqnzcxbfvwr95fk8pn6q-gnupg-2.4.9/bin/gpg
|
||||
✅ pre-commit
|
||||
pre-commit 4.5.1
|
||||
/nix/store/n981w6hjfar2l81kxbxs2wxl64vwa5kj-pre-commit-4.5.1/bin/pre-commit
|
||||
✅ run-clang-tidy
|
||||
usage: run-clang-tidy [-h] [-allow-enabling-alpha-checkers]
|
||||
/nix/store/4z2fyklg78klallr7x9j02kz92hnxp4m-run-clang-tidy/bin/run-clang-tidy
|
||||
✅ run-clang-tidy-22
|
||||
usage: run-clang-tidy [-h] [-allow-enabling-alpha-checkers]
|
||||
/nix/store/f8m0p9ad40brp9ahy4i0h27kqjkya1j9-run-clang-tidy-22/bin/run-clang-tidy-22
|
||||
[ ok ] ccache ccache version 4.13.6
|
||||
[ ok ] clang clang version 22.1.7
|
||||
[ ok ] clang++ clang version 22.1.7
|
||||
[ ok ] ClangBuildAnalyzer ClangBuildAnalyzer 1.6.0
|
||||
[ ok ] curl curl 8.20.0 (aarch64-unknown-linux-gnu) libcurl/8.20.0 OpenSSL/3.6.2 zlib/1.3.2 libssh2/1.11.1 nghttp2/1.69.0 mit-krb5/1.22.1
|
||||
[ ok ] file file-5.47
|
||||
[ ok ] less less 692 (PCRE2 regular expressions)
|
||||
[ ok ] make GNU Make 4.4.1
|
||||
[ ok ] netstat net-tools 2.10
|
||||
[ ok ] ninja 1.13.2
|
||||
[ ok ] perl v5.42.0
|
||||
[ ok ] pkg-config 0.29.2
|
||||
[ ok ] vim VIM - Vi IMproved 9.2 (2026 Feb 14, compiled Jan 01 1980 00:00:00)
|
||||
[ ok ] zip Zip 3.0
|
||||
[ ok ] clang-format clang-format version 22.1.7
|
||||
[ ok ] dot dot - graphviz version 12.2.1 (0)
|
||||
[ ok ] doxygen 1.16.1
|
||||
[ ok ] gcovr gcovr 8.4
|
||||
[ ok ] gh gh version 2.94.0 (nixpkgs)
|
||||
[ ok ] git-cliff git-cliff 2.13.1
|
||||
[ ok ] git-lfs git-lfs/3.7.1 (3.7.1; linux arm64; go 1.26.3)
|
||||
[ ok ] gpg gpg (GnuPG) 2.4.9
|
||||
[ ok ] pre-commit pre-commit 4.5.1
|
||||
[ ok ] run-clang-tidy usage: run-clang-tidy [-h] [-allow-enabling-alpha-checkers]
|
||||
|
||||
Rust toolchain:
|
||||
✅ cargo
|
||||
cargo 1.95.0 (f2d3ce0bd 2026-03-21)
|
||||
/nix/store/yw1rs50s6qpsw0zyl7j3dpm18swbl0ag-cargo-1.95.0-aarch64-unknown-linux-gnu/bin/cargo
|
||||
✅ cargo-audit
|
||||
cargo-audit-audit 0.22.1
|
||||
/nix/store/9rxbrn9aa2r1z96186s69pc7vzizyfch-cargo-audit-0.22.1/bin/cargo-audit
|
||||
✅ cargo-llvm-cov
|
||||
cargo-llvm-cov 0.8.5
|
||||
/nix/store/vwjsi159n89szrx4yh5pc3jlf2gp4fld-cargo-llvm-cov-0.8.5/bin/cargo-llvm-cov
|
||||
✅ cargo-nextest
|
||||
cargo-nextest 0.9.137
|
||||
/nix/store/qb6bcg2fjvm3r9s9j98nmffmf9xwh45s-cargo-nextest-0.9.137/bin/cargo-nextest
|
||||
✅ clippy-driver
|
||||
clippy 0.1.95 (59807616e1 2026-04-14)
|
||||
/nix/store/nz4qv12pf16c092qr9hh4dsn0fzf47da-rust-minimal-1.95.0/bin/clippy-driver
|
||||
✅ rust-analyzer
|
||||
rust-analyzer 1.95.0 (5980761 2026-04-14)
|
||||
/nix/store/m1rn67sqfz8s44idcxqallg680ifk71r-rust-analyzer-preview-1.95.0-aarch64-unknown-linux-gnu/bin/rust-analyzer
|
||||
✅ rustc
|
||||
rustc 1.95.0 (59807616e 2026-04-14)
|
||||
/nix/store/nz4qv12pf16c092qr9hh4dsn0fzf47da-rust-minimal-1.95.0/bin/rustc
|
||||
✅ rustfmt
|
||||
rustfmt 1.9.0-stable (59807616e1 2026-04-14)
|
||||
/nix/store/jidfsprj2820glyzjn54ldn3j1fmz8c5-rustfmt-preview-1.95.0-aarch64-unknown-linux-gnu/bin/rustfmt
|
||||
[ ok ] cargo cargo 1.95.0 (f2d3ce0bd 2026-03-21)
|
||||
[ ok ] cargo-audit cargo-audit-audit 0.22.1
|
||||
[ ok ] cargo-llvm-cov cargo-llvm-cov 0.8.5
|
||||
[ ok ] cargo-nextest cargo-nextest 0.9.137
|
||||
[ ok ] clippy clippy 0.1.95 (59807616e1 2026-04-14)
|
||||
[ ok ] rust-analyzer rust-analyzer 1.95.0 (5980761 2026-04-14)
|
||||
[ ok ] rustc rustc 1.95.0 (59807616e 2026-04-14)
|
||||
[ ok ] rustfmt rustfmt 1.9.0-stable (59807616e1 2026-04-14)
|
||||
|
||||
GCC toolchain:
|
||||
✅ gcc
|
||||
gcc (GCC) 15.2.0
|
||||
/nix/store/rn6svg593xsmn8qcjzk8x9pa1i62c4kb-gcc-wrapper-15.2.0/bin/gcc
|
||||
✅ gcc-15
|
||||
gcc (GCC) 15.2.0
|
||||
/nix/store/h489d1rmjisfbxh5kmsb0a7c35j8qsdf-gcc-15/bin/gcc-15
|
||||
✅ g++
|
||||
g++ (GCC) 15.2.0
|
||||
/nix/store/rn6svg593xsmn8qcjzk8x9pa1i62c4kb-gcc-wrapper-15.2.0/bin/g++
|
||||
✅ g++-15
|
||||
g++ (GCC) 15.2.0
|
||||
/nix/store/9ywmhz8bmzknrn3pn84g46z8hj3vrmw5-g++-15/bin/g++-15
|
||||
✅ cpp
|
||||
cpp (GCC) 15.2.0
|
||||
/nix/store/rn6svg593xsmn8qcjzk8x9pa1i62c4kb-gcc-wrapper-15.2.0/bin/cpp
|
||||
✅ cpp-15
|
||||
cpp (GCC) 15.2.0
|
||||
/nix/store/vmjilh1b830qz9yh0a1jj5ads0jxizdk-cpp-15/bin/cpp-15
|
||||
✅ gcov
|
||||
gcov (GCC) 15.2.0
|
||||
/nix/store/rmwf5hpi1y2m1wpnfvlxmrhksm4djk2j-gcc-15.2.0/bin/gcov
|
||||
[ ok ] gcc gcc (GCC) 15.2.0
|
||||
[ ok ] g++ g++ (GCC) 15.2.0
|
||||
[ ok ] gcov gcov (GCC) 15.2.0
|
||||
|
||||
Mold:
|
||||
✅ mold
|
||||
mold 2.41.0 (compatible with GNU ld)
|
||||
/nix/store/f5qh5a0bx1dslmnf5n5gx0s6aljbswq3-mold-unwrapped-wrapper-2.41.0/bin/mold
|
||||
[ ok ] mold mold 2.41.0 (compatible with GNU ld)
|
||||
|
||||
Skipping git-over-HTTPS check (CHECK_TOOLS_SKIP_CLONE is set).
|
||||
|
||||
✅ All 52 checked tools are present and runnable.
|
||||
All 40 checked tools are present and runnable.
|
||||
|
||||
@@ -1,39 +1,67 @@
|
||||
# The environment CI builds in: every tool on PATH, no Nix stdenv setup hooks.
|
||||
# Baked into the `nix-*` Docker images on Linux (see nix/docker), built on the
|
||||
# runner on macOS (see .github/actions/setup-nix-env).
|
||||
{
|
||||
pkgs,
|
||||
customGlibc,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (import ./packages.nix { inherit pkgs; }) commonPackages;
|
||||
inherit (import ./packages.nix { inherit pkgs; })
|
||||
commonPackages
|
||||
gccVersion
|
||||
llvmVersion
|
||||
mkVersionedToolLinks
|
||||
;
|
||||
|
||||
# Each forces something absent on the other platform, so both stay lazy.
|
||||
linux = import ./linux.nix { inherit pkgs customGlibc; };
|
||||
darwin = import ./darwin.nix { inherit pkgs; };
|
||||
# Custom-glibc toolchain, shared with the Linux dev shell (see compilers.nix).
|
||||
inherit (import ./compilers.nix { inherit pkgs customGlibc; })
|
||||
customGcc
|
||||
customClang
|
||||
customBinutils
|
||||
customGcov
|
||||
;
|
||||
|
||||
# What a buildEnv cannot express: environment variables. $GITHUB_ENV format;
|
||||
# `set -a; . env; set +a` loads it in a shell.
|
||||
darwinEnv = pkgs.writeTextDir "share/xrpld-ci-env/env" (
|
||||
pkgs.lib.concatStrings (
|
||||
pkgs.lib.mapAttrsToList (name: value: "${name}=${value}\n") (darwin.sdkEnv // darwin.libresolvEnv)
|
||||
)
|
||||
);
|
||||
# Strip the generic cc/c++/cpp symlinks from the clang wrapper so it can
|
||||
# coexist with the gcc wrapper in buildEnv. gcc remains the default
|
||||
# compiler (cc/c++/cpp); clang is invoked explicitly as clang/clang++.
|
||||
customClangForCiEnv = pkgs.symlinkJoin {
|
||||
name = "clang-wrapper-custom-for-ci-env";
|
||||
paths = [ customClang ];
|
||||
postBuild = ''
|
||||
rm -f $out/bin/cc $out/bin/c++ $out/bin/cpp
|
||||
'';
|
||||
};
|
||||
|
||||
toolchain = if pkgs.stdenv.isLinux then linux.toolchain else (darwin.toolchain ++ [ darwinEnv ]);
|
||||
in
|
||||
{
|
||||
default = pkgs.buildEnv {
|
||||
name = "xrpld-ci-env";
|
||||
paths =
|
||||
commonPackages
|
||||
++ toolchain
|
||||
++ [
|
||||
# CA certificate bundle so HTTPS clients (git, curl, conan) can verify
|
||||
# TLS connections without ca-certificates being installed in the system.
|
||||
pkgs.cacert
|
||||
];
|
||||
paths = commonPackages ++ [
|
||||
customGcc
|
||||
customGcov
|
||||
customClangForCiEnv
|
||||
customBinutils
|
||||
(mkVersionedToolLinks {
|
||||
name = "gcc";
|
||||
package = customGcc;
|
||||
version = gccVersion;
|
||||
tools = [
|
||||
"gcc"
|
||||
"g++"
|
||||
"cpp"
|
||||
];
|
||||
})
|
||||
(mkVersionedToolLinks {
|
||||
name = "clang";
|
||||
package = customClang;
|
||||
version = llvmVersion;
|
||||
tools = [
|
||||
"clang"
|
||||
"clang++"
|
||||
];
|
||||
})
|
||||
# CA certificate bundle so HTTPS clients (git, curl, conan) can verify
|
||||
# TLS connections without ca-certificates being installed in the system.
|
||||
pkgs.cacert
|
||||
];
|
||||
pathsToLink = [
|
||||
"/bin"
|
||||
"/etc/ssl/certs"
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
# The Linux toolchain: gcc / clang / binutils rebuilt to target the pinned
|
||||
# custom glibc, shared by the CI environment (ci-env.nix) and the dev shell
|
||||
# (devshell.nix). The counterpart to darwin.nix.
|
||||
#
|
||||
# Linux only — the pinned glibc snapshot does not build on darwin, so callers
|
||||
# must not evaluate this on macOS.
|
||||
# Custom-glibc compiler toolchain shared by the CI environment (ci-env.nix) and
|
||||
# the Linux dev shell (devshell.nix): gcc / clang / binutils rebuilt to target
|
||||
# the pinned custom glibc. Linux only — the pinned glibc snapshot does not build
|
||||
# on darwin, so callers must not evaluate this on macOS.
|
||||
{
|
||||
pkgs,
|
||||
customGlibc,
|
||||
@@ -11,11 +9,9 @@
|
||||
let
|
||||
inherit (import ./packages.nix { inherit pkgs; })
|
||||
gccPackage
|
||||
gccVersion
|
||||
llvmPackages
|
||||
llvmVersion
|
||||
mkGcov
|
||||
mkVersionedToolLinks
|
||||
;
|
||||
|
||||
# binutils wrapped to emit binaries that reference the custom glibc
|
||||
@@ -107,46 +103,15 @@ let
|
||||
echo "-isystem ${customCompilerRt.dev}/include" >> $out/nix-support/cc-cflags
|
||||
'';
|
||||
};
|
||||
# Strip the generic cc/c++/cpp symlinks from the clang wrapper so it can
|
||||
# coexist with the gcc wrapper in buildEnv. gcc remains the default
|
||||
# compiler (cc/c++/cpp); clang is invoked explicitly as clang/clang++.
|
||||
customClangForCiEnv = pkgs.symlinkJoin {
|
||||
name = "clang-wrapper-custom-for-ci-env";
|
||||
paths = [ customClang ];
|
||||
postBuild = ''
|
||||
rm -f $out/bin/cc $out/bin/c++ $out/bin/cpp
|
||||
'';
|
||||
};
|
||||
in
|
||||
{
|
||||
# For an environment that only puts binaries on PATH.
|
||||
toolchain = [
|
||||
inherit
|
||||
customGcc
|
||||
customGcov
|
||||
customClangForCiEnv
|
||||
customClang
|
||||
customBinutils
|
||||
(mkVersionedToolLinks {
|
||||
name = "gcc";
|
||||
package = customGcc;
|
||||
version = gccVersion;
|
||||
tools = [
|
||||
"gcc"
|
||||
"g++"
|
||||
"cpp"
|
||||
];
|
||||
})
|
||||
(mkVersionedToolLinks {
|
||||
name = "clang";
|
||||
package = customClang;
|
||||
version = llvmVersion;
|
||||
tools = [
|
||||
"clang"
|
||||
"clang++"
|
||||
];
|
||||
})
|
||||
];
|
||||
customStdenv
|
||||
customGcov
|
||||
;
|
||||
|
||||
gccStdenv = customStdenv;
|
||||
clangStdenv = pkgs.stdenvAdapters.overrideCC pkgs.stdenv customClang;
|
||||
gcov = customGcov;
|
||||
customClangStdenv = pkgs.stdenvAdapters.overrideCC pkgs.stdenv customClang;
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
# The darwin toolchain, counterpart to linux.nix. Split by consumer: a dev
|
||||
# shell's stdenv provides the SDK variables, nothing provides libresolv.
|
||||
#
|
||||
# darwin only - `libresolv` does not exist on Linux.
|
||||
{ pkgs }:
|
||||
let
|
||||
inherit (import ./packages.nix { inherit pkgs; })
|
||||
llvmVersion
|
||||
llvmPackages
|
||||
mkVersionedToolLinks
|
||||
;
|
||||
|
||||
# nixpkgs keeps libresolv out of the macOS SDK, so neither c-ares' `-lresolv`
|
||||
# nor grpc's <arpa/nameser.h> resolves. Headers can come from nixpkgs; the
|
||||
# library cannot, or its store path lands in xrpld - hence this copy.
|
||||
libresolvSystemStub =
|
||||
pkgs.runCommand "libresolv-system-stub"
|
||||
{
|
||||
nativeBuildInputs = [ llvmPackages.bintools ];
|
||||
}
|
||||
''
|
||||
mkdir -p "$out/lib"
|
||||
cp ${pkgs.darwin.libresolv}/lib/libresolv.9.dylib "$out/lib/"
|
||||
chmod +w "$out/lib/libresolv.9.dylib"
|
||||
llvm-install-name-tool -id /usr/lib/libresolv.9.dylib "$out/lib/libresolv.9.dylib"
|
||||
ln -s libresolv.9.dylib "$out/lib/libresolv.dylib"
|
||||
'';
|
||||
in
|
||||
{
|
||||
# For an environment that only puts binaries on PATH.
|
||||
toolchain = [
|
||||
llvmPackages.clang
|
||||
# The wrappers re-export only part of cctools; a bare env has no stdenv to
|
||||
# supply the rest, and without `dsymutil` even `clang -g` cannot link. One
|
||||
# by one, because buildEnv rejects any name a wrapper owns (notably `ld`).
|
||||
(pkgs.linkFarm "cctools-extra" (
|
||||
map
|
||||
(tool: {
|
||||
name = "bin/${tool}";
|
||||
path = "${llvmPackages.clang.bintools.bintools}/bin/${tool}";
|
||||
})
|
||||
[
|
||||
"codesign_allocate"
|
||||
"dsymutil"
|
||||
"dwarfdump"
|
||||
"install_name_tool"
|
||||
"lipo"
|
||||
"otool"
|
||||
]
|
||||
))
|
||||
(mkVersionedToolLinks {
|
||||
name = "clang";
|
||||
package = llvmPackages.clang;
|
||||
version = llvmVersion;
|
||||
tools = [
|
||||
"clang"
|
||||
"clang++"
|
||||
];
|
||||
})
|
||||
];
|
||||
|
||||
# Without these CMake asks `xcrun` and gets the Command Line Tools SDK, whose
|
||||
# headers clash with the Nix libc++ ones.
|
||||
sdkEnv = {
|
||||
DEVELOPER_DIR = "${pkgs.apple-sdk}";
|
||||
SDKROOT = "${pkgs.apple-sdk}/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk";
|
||||
};
|
||||
|
||||
# Salted names: the wrappers only read plain NIX_CFLAGS_COMPILE / NIX_LDFLAGS
|
||||
# through role variables a Nix stdenv would set. The salt is the target
|
||||
# platform, so this fits the gcc wrapper too.
|
||||
#
|
||||
# No space after -isystem: these are written one per line as KEY=VALUE, and a
|
||||
# shell sourcing that reads the space as the end of the assignment.
|
||||
libresolvEnv = {
|
||||
"NIX_CFLAGS_COMPILE_${llvmPackages.clang.suffixSalt}" =
|
||||
"-isystem${pkgs.darwin.libresolv.dev}/include";
|
||||
"NIX_LDFLAGS_${llvmPackages.clang.bintools.suffixSalt}" = "-L${libresolvSystemStub}/lib";
|
||||
};
|
||||
}
|
||||
@@ -14,21 +14,21 @@ let
|
||||
plainGccStdenv = pkgs."gcc${toString gccVersion}Stdenv";
|
||||
plainClangStdenv = llvmPackages.stdenv;
|
||||
|
||||
# Each forces something absent on the other platform, so both stay lazy.
|
||||
linux = import ./linux.nix { inherit pkgs customGlibc; };
|
||||
darwin = import ./darwin.nix { inherit pkgs; };
|
||||
|
||||
# Custom-glibc stdenvs, matching the CI environment. darwin has no custom
|
||||
# glibc, so there they fall back to the plain nixpkgs stdenvs.
|
||||
customGccStdenv = if pkgs.stdenv.isLinux then linux.gccStdenv else plainGccStdenv;
|
||||
customClangStdenv = if pkgs.stdenv.isLinux then linux.clangStdenv else plainClangStdenv;
|
||||
# Custom-glibc stdenvs, matching the CI environment (see compilers.nix). The
|
||||
# pinned glibc snapshot only builds on Linux, so on darwin these fall back to
|
||||
# the plain stdenvs; the `if isLinux` guard keeps `customGlibc` from being
|
||||
# forced (and erroring) on macOS.
|
||||
customCompilers = import ./compilers.nix { inherit pkgs customGlibc; };
|
||||
customGccStdenv = if pkgs.stdenv.isLinux then customCompilers.customStdenv else plainGccStdenv;
|
||||
customClangStdenv =
|
||||
if pkgs.stdenv.isLinux then customCompilers.customClangStdenv else plainClangStdenv;
|
||||
|
||||
# gcov matching each gcc shell, so `-Dcoverage=ON` builds work in the shell.
|
||||
plainGcov = mkGcov {
|
||||
name = "plain";
|
||||
cc = gccPackage.cc;
|
||||
};
|
||||
customGccGcov = if pkgs.stdenv.isLinux then linux.gcov else plainGcov;
|
||||
customGccGcov = if pkgs.stdenv.isLinux then customCompilers.customGcov else plainGcov;
|
||||
|
||||
# Whole directory: init.sh locates the profiles relative to itself.
|
||||
conanDir = ../conan;
|
||||
@@ -49,16 +49,6 @@ let
|
||||
unset _xrpl_conan_stamp
|
||||
'';
|
||||
|
||||
# Not sdkEnv: a shell's stdenv already sets that up. Prepended so the stub
|
||||
# beats the nixpkgs libresolv this shell's tooling drags in.
|
||||
darwinLibresolvHook = pkgs.lib.optionalString pkgs.stdenv.isDarwin (
|
||||
pkgs.lib.concatLines (
|
||||
pkgs.lib.mapAttrsToList (
|
||||
name: value: ''export ${name}="${value} ''${${name}:-}"''
|
||||
) darwin.libresolvEnv
|
||||
)
|
||||
);
|
||||
|
||||
# Shown when entering a *-plain shell. These exist only on Linux (see below),
|
||||
# where the stock toolchain diverges from CI.
|
||||
plainWarningHook = ''
|
||||
@@ -116,7 +106,6 @@ let
|
||||
shellHook = ''
|
||||
echo "Welcome to xrpld development shell";
|
||||
${compilerVersionHook}
|
||||
${darwinLibresolvHook}
|
||||
${conanHook}
|
||||
${warningHook}
|
||||
'';
|
||||
|
||||
@@ -8,7 +8,7 @@ RUN mkdir -p ~/.config/nix && \
|
||||
|
||||
# Copy our source and setup our working dir.
|
||||
COPY nix/ci-env.nix /tmp/build/nix/ci-env.nix
|
||||
COPY nix/linux.nix /tmp/build/nix/linux.nix
|
||||
COPY nix/compilers.nix /tmp/build/nix/compilers.nix
|
||||
COPY nix/packages.nix /tmp/build/nix/packages.nix
|
||||
COPY nix/utils.nix /tmp/build/nix/utils.nix
|
||||
COPY flake.nix /tmp/build/
|
||||
|
||||
@@ -50,9 +50,6 @@ let
|
||||
# environment (the plain stdenv compiler in the dev shell, the custom-glibc
|
||||
# wrappers in ci-env.nix), so those callers pass their own `package`; the
|
||||
# clang tooling is environment-independent and is linked in commonPackages.
|
||||
#
|
||||
# Exec wrappers, not symlinks: the nixpkgs clang-tools wrapper dispatches on
|
||||
# `$(basename $0)-unwrapped`, which a suffixed symlink turns into a dead path.
|
||||
mkVersionedToolLinks =
|
||||
{
|
||||
name,
|
||||
@@ -60,15 +57,12 @@ let
|
||||
version,
|
||||
tools,
|
||||
}:
|
||||
pkgs.symlinkJoin {
|
||||
name = "${name}-${toString version}-versioned-links";
|
||||
paths = map (
|
||||
tool:
|
||||
pkgs.writeShellScriptBin "${tool}-${toString version}" ''
|
||||
exec "${package}/bin/${tool}" "$@"
|
||||
''
|
||||
) tools;
|
||||
};
|
||||
pkgs.linkFarm "${name}-${toString version}-versioned-links" (
|
||||
map (tool: {
|
||||
name = "bin/${tool}-${toString version}";
|
||||
path = "${package}/bin/${tool}";
|
||||
}) tools
|
||||
);
|
||||
|
||||
# The cc-wrapper doesn't re-export gcov, but coverage tooling (gcovr) needs a
|
||||
# gcov that exactly matches the compiler. Surface it from a gcc `cc` output.
|
||||
|
||||
@@ -2,6 +2,13 @@ ARG BASE_IMAGE=debian:bookworm
|
||||
|
||||
FROM ${BASE_IMAGE}
|
||||
|
||||
# Packaging runs in a vanilla distro image, so the tooling has to come
|
||||
# from the distro's archive: debhelper for deb, rpm-build (and the
|
||||
# systemd / find-debuginfo macros it depends on) for rpm.
|
||||
# The container also uses git (real history) for
|
||||
# build_pkg.sh's SOURCE_DATE_EPOCH; otherwise it falls back to a tarball
|
||||
# download and the timestamp comes from wall-clock time.
|
||||
|
||||
COPY package/install-packaging-tools.sh /tmp/install-packaging-tools.sh
|
||||
|
||||
RUN /tmp/install-packaging-tools.sh
|
||||
|
||||
@@ -8,9 +8,7 @@ a build configured with `-Dvalidator_keys=ON`.
|
||||
|
||||
```
|
||||
package/
|
||||
build_pkg.sh Staging and build script (called by the CMake `package` target and CI)
|
||||
sign_rpm.sh Signs the built RPMs (called by CI when publishing)
|
||||
publish_pkg.sh Uploads built packages to the XRPLF Nexus repositories (called by CI)
|
||||
build_pkg.sh Staging and build script (called by the CMake `package` target and CI)
|
||||
rpm/
|
||||
xrpld.spec RPM spec
|
||||
debian/ Debian control files (control, rules, copyright, xrpld.docs, xrpld.links, source/format)
|
||||
@@ -33,7 +31,7 @@ package manager (`apt-get` -> deb, `dnf`/`yum` -> rpm).
|
||||
|
||||
| Package type | Image (`package_configs.<distro>[].image` in `linux.json`) | Tools required |
|
||||
| ------------ | ---------------------------------------------------------- | --------------------------------------------------- |
|
||||
| RPM | `ghcr.io/xrplf/xrpld/packaging-rhel:sha-<sha>` | `rpmbuild`, `rpmsign` |
|
||||
| RPM | `ghcr.io/xrplf/xrpld/packaging-rhel:sha-<sha>` | `rpmbuild` |
|
||||
| DEB | `ghcr.io/xrplf/xrpld/packaging-debian:sha-<sha>` | `dpkg-buildpackage`, debhelper with compat level 13 |
|
||||
|
||||
To print the full packaging matrix (artifact names and images) for the current
|
||||
@@ -89,7 +87,7 @@ docker run --rm \
|
||||
./package/build_pkg.sh --pkg-release "${PKG_RELEASE}"
|
||||
|
||||
# Output:
|
||||
# build/debbuild/*.deb (DEB + dbgsym; Debian names both .deb)
|
||||
# build/debbuild/*.deb (DEB + dbgsym .ddeb)
|
||||
# build/rpmbuild/RPMS/x86_64/*.rpm
|
||||
```
|
||||
|
||||
@@ -122,56 +120,6 @@ The package version is not a CMake input on this path: `build_pkg.sh` derives it
|
||||
from the just-built `xrpld` binary's `xrpld --version` output. The package
|
||||
release defaults to 1 and is overridable with `-Dpkg_release=N`.
|
||||
|
||||
## Publishing packages
|
||||
|
||||
Packages are published to the XRPLF repositories on Sonatype Nexus at
|
||||
`https://packages.xrplf.org`. The `release-info` action decides the channel from
|
||||
the event, and `publish_pkg.sh` maps that channel to its repositories:
|
||||
|
||||
| Event | Version | Channel | DEB repository | RPM upload repository |
|
||||
| ------------------------ | ----------------- | -------------- | ------------------ | ------------------------- |
|
||||
| tag | `X.Y.Z` | `stable` | `deb-stable` | `rpm-stable-hosted` |
|
||||
| tag | `X.Y.Z-rcN` | `unstable` | `deb-unstable` | `rpm-unstable-hosted` |
|
||||
| tag | `X.Y.Z-bN` | `experimental` | `deb-experimental` | `rpm-experimental-hosted` |
|
||||
| push to `develop` | `xrpld --version` | `develop` | `deb-develop` | `rpm-develop-hosted` |
|
||||
| tag, non-public codebase | _any_ | `private` | `deb-private` | `rpm-private-hosted` |
|
||||
|
||||
Only a tag names a channel — do not extend that to `develop`, where
|
||||
`BuildInfo.cpp`'s `versionString` moves through `-bN`, `-rcN` and even the final
|
||||
version during a release cycle, which would send develop builds into `stable`.
|
||||
Versions sort in row order, so moving to a more mature channel never downgrades.
|
||||
|
||||
The action decides the package release number on the same split: a tag's version
|
||||
is unique, so its packages are release 1, while develop repeats the same version
|
||||
and takes `github.run_number` so each push supersedes the last. Both reach the
|
||||
packaging scripts as arguments, so neither script derives anything itself.
|
||||
|
||||
Publishing is the last step of each packaging job, uploading from the container
|
||||
that built the packages. It runs when the caller passes `publish: true`:
|
||||
`on-trigger.yml` for develop pushes in `XRPLF/rippled`, `on-tag.yml` for tags in
|
||||
any `XRPLF` repository, `on-pr.yml` never. Both authenticate with the
|
||||
`NEXUS_REMOTE_USERNAME` / `NEXUS_REMOTE_PASSWORD` secrets already used for the
|
||||
Conan remote.
|
||||
|
||||
Nexus owns the repository metadata; nothing here indexes anything. Worth knowing:
|
||||
|
||||
- Each apt-hosted repository needs a distribution (ours use `any`) and a PGP
|
||||
signing keypair configured in Nexus, which rejects one created without a
|
||||
keypair. Nexus signs the apt metadata with it, never the packages.
|
||||
- Hosted yum repositories cannot be signed by Nexus, so each `rpm-<channel>-hosted`
|
||||
repository sits behind a `rpm-<channel>` yum group repository whose metadata
|
||||
Nexus signs. Uploads go to the hosted repository; clients point at the group
|
||||
and verify the metadata with `repo_gpgcheck=1`. Nexus never signs the RPMs
|
||||
themselves, so `sign_rpm.sh` signs them before they are uploaded, and clients
|
||||
verify them with `gpgcheck=1`.
|
||||
- yum metadata is rebuilt asynchronously, so a successful publish is not
|
||||
immediately installable.
|
||||
- Each job uploads only what it built, and uploads are not transactional, so a
|
||||
failure can leave one format published alone. Re-running is safe: both the apt
|
||||
POST and the yum PUT replace an existing asset.
|
||||
- The `develop` repositories gain a package per push, so they need a cleanup
|
||||
policy to stay bounded; tagged channels publish each version once.
|
||||
|
||||
## How `build_pkg.sh` works
|
||||
|
||||
`build_pkg.sh` derives the `xrpld` software version from
|
||||
@@ -203,9 +151,10 @@ With `PKG_RELEASE=1`, the package metadata becomes:
|
||||
| `3.2.0-b1` | `3.2.0~b1-1%{?dist}` | `3.2.0~b1-1` |
|
||||
| `3.2.0-rc1` | `3.2.0~rc1-1%{?dist}` | `3.2.0~rc1-1` |
|
||||
|
||||
The Debian changelog entry carries the channel passed as `--channel`
|
||||
(`PKG_CHANNEL`), defaulting to `unstable`. An unsupported pre-release, and build
|
||||
metadata on a final release such as `3.2.0+abc123`, are both rejected.
|
||||
The Debian changelog entry carries the repository component: final releases use
|
||||
`stable`, `b0` builds, including `b0+metadata`, use `develop`, and `bN`/`rcN`
|
||||
pre-releases use `unstable`.
|
||||
Build metadata on a final release, such as `3.2.0+abc123`, is rejected.
|
||||
|
||||
The RPM path intentionally uses `~` in `Version`, matching the Debian
|
||||
pre-release ordering convention, so RPM filenames/NVRs begin with forms like
|
||||
@@ -219,12 +168,8 @@ fail early.
|
||||
Flags are for explicit invocation; environment variables are intended for
|
||||
CMake/CI integration. The CI workflow and the CMake `package` target both invoke
|
||||
`build_pkg.sh` with no flags; CMake supplies `SRC_DIR`, `BUILD_DIR`, and
|
||||
`PKG_RELEASE` via env, while CI supplies `BUILD_DIR`, `PKG_RELEASE` and
|
||||
`PKG_CHANNEL` via env and lets the script use defaults for the rest.
|
||||
|
||||
Signing is not part of this script. `sign_rpm.sh` does it in a separate CI step
|
||||
that only runs when publishing, so a published RPM is always signed and a local
|
||||
build never needs a key.
|
||||
`PKG_RELEASE` via env, while CI supplies `BUILD_DIR` and `PKG_RELEASE` via env
|
||||
and lets the script use defaults for the rest.
|
||||
|
||||
It resolves `SRC_DIR` and `BUILD_DIR` to absolute paths, then calls
|
||||
`stage_common()` to copy the `xrpld` and `validator-keys` binaries, config files,
|
||||
@@ -241,9 +186,14 @@ what catches a binary still linked against the Nix store's ELF loader (see
|
||||
3. Runs `rpmbuild -bb`, passing the normalized package metadata version as the
|
||||
`pkg_version` RPM macro and `PKG_RELEASE` as the `pkg_release` RPM macro.
|
||||
The spec uses manual `install` commands to place files, disables `dwz`, and
|
||||
generates debuginfo packages.
|
||||
writes uncompressed RPM payloads while generating debuginfo packages.
|
||||
4. Output: `rpmbuild/RPMS/x86_64/xrpld-*.rpm`
|
||||
|
||||
The uncompressed RPM payload setting is intentionally unconditional for
|
||||
generated RPMs. It trades larger RPM artifacts for much shorter package
|
||||
build/validation time, which keeps RPM package validation in the same rough time
|
||||
class as Debian package validation.
|
||||
|
||||
RPM upgrades intentionally do not restart a running `xrpld` service. The spec
|
||||
uses `%systemd_postun`, matching Debian's `dh_installsystemd
|
||||
--no-stop-on-upgrade` behavior; operators pick up the new binary on the next
|
||||
@@ -259,20 +209,17 @@ service restart.
|
||||
5. Generates a minimal `debian/changelog` using `${pkg_version}-${PKG_RELEASE}`,
|
||||
where `pkg_version` is derived from the binary-reported `xrpld` version.
|
||||
6. Runs `dpkg-buildpackage -b --no-sign -d` (`-d` skips the build-dependency check, since the binary is already built). `debian/rules` uses manual `install` commands.
|
||||
7. Output: `debbuild/*.deb`, the binary package and the `-dbgsym` package.
|
||||
Debian gives dbgsym packages a `.deb` extension; only Ubuntu uses `.ddeb`.
|
||||
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
|
||||
|
||||
# Optional, and not in the packaging image: apt-get install -y lintian
|
||||
lintian -I debbuild/*.deb
|
||||
```
|
||||
|
||||
## Reproducibility
|
||||
|
||||
@@ -16,8 +16,6 @@ Options (each can also be set via the env var shown):
|
||||
xrpld and validator-keys
|
||||
binaries [BUILD_DIR; default: ${PWD}/build]
|
||||
--pkg-release N package release iteration [PKG_RELEASE; default: 1]
|
||||
--channel NAME release channel, written
|
||||
to debian/changelog [PKG_CHANNEL; default: unstable]
|
||||
--source-date-epoch SECS reproducibility timestamp [SOURCE_DATE_EPOCH; latest git ctime; fallback: current time]
|
||||
-h, --help show this help and exit
|
||||
EOF
|
||||
@@ -34,7 +32,6 @@ need_arg() {
|
||||
SRC_DIR="${SRC_DIR:-}"
|
||||
BUILD_DIR="${BUILD_DIR:-}"
|
||||
PKG_RELEASE="${PKG_RELEASE:-1}"
|
||||
PKG_CHANNEL="${PKG_CHANNEL:-unstable}"
|
||||
SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:-}"
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
@@ -54,11 +51,6 @@ while [[ $# -gt 0 ]]; do
|
||||
PKG_RELEASE="$2"
|
||||
shift 2
|
||||
;;
|
||||
--channel)
|
||||
need_arg "$@"
|
||||
PKG_CHANNEL="$2"
|
||||
shift 2
|
||||
;;
|
||||
--source-date-epoch)
|
||||
need_arg "$@"
|
||||
SOURCE_DATE_EPOCH="$2"
|
||||
@@ -206,6 +198,7 @@ stage_common() {
|
||||
|
||||
build_rpm() {
|
||||
local topdir="${BUILD_DIR}/rpmbuild"
|
||||
rm -rf "${topdir}"
|
||||
mkdir -p "${topdir}"/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}
|
||||
|
||||
cp "${SRC_DIR}/package/rpm/xrpld.spec" "${topdir}/SPECS/xrpld.spec"
|
||||
@@ -221,6 +214,7 @@ build_rpm() {
|
||||
|
||||
build_deb() {
|
||||
local staging="${BUILD_DIR}/debbuild/source"
|
||||
rm -rf "${staging}"
|
||||
mkdir -p "${staging}"
|
||||
|
||||
stage_common "${staging}"
|
||||
@@ -231,9 +225,25 @@ build_deb() {
|
||||
cp "${staging}/xrpld.tmpfiles" "${staging}/debian/xrpld.tmpfiles"
|
||||
cp "${staging}/xrpld.logrotate" "${staging}/debian/xrpld.logrotate"
|
||||
|
||||
# Choose the Debian repository component for this package.
|
||||
# 3.2.0 -> stable, *-b0[+metadata] -> develop,
|
||||
# bN/rcN pre-releases -> unstable.
|
||||
local deb_component
|
||||
if [[ -z "${pre_release}" ]]; then
|
||||
deb_component="stable"
|
||||
elif [[ "${pre_release}" =~ ^b0(\+.*)?$ ]]; then
|
||||
deb_component="develop"
|
||||
elif [[ "${pre_release}" =~ ^(b[1-9][0-9]*|rc[0-9]+)(\+.*)?$ ]]; then
|
||||
deb_component="unstable"
|
||||
else
|
||||
echo "build_pkg.sh: unsupported xrpld pre-release '${pre_release}'." >&2
|
||||
echo "Use bN or rcN, e.g. 3.2.0-b1 or 3.2.0-rc2." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Debian version is <upstream>[~<pre>]-<pkg release>.
|
||||
cat >"${staging}/debian/changelog" <<EOF
|
||||
xrpld (${pkg_version}-${PKG_RELEASE}) ${PKG_CHANNEL}; urgency=medium
|
||||
xrpld (${pkg_version}-${PKG_RELEASE}) ${deb_component}; urgency=medium
|
||||
* Release ${xrpld_version}.
|
||||
|
||||
-- XRPL Foundation <contact@xrplf.org> ${CHANGELOG_DATE}
|
||||
@@ -245,8 +255,4 @@ EOF
|
||||
(cd "${staging}" && dpkg-buildpackage -b --no-sign -d)
|
||||
}
|
||||
|
||||
# Remove both build directories, because a package left from an earlier build
|
||||
# would otherwise be picked up and published alongside this one.
|
||||
rm -rf "${BUILD_DIR}/debbuild" "${BUILD_DIR}/rpmbuild"
|
||||
|
||||
"build_${pkg_type}"
|
||||
|
||||
@@ -22,24 +22,12 @@ case "${ID}" in
|
||||
;;
|
||||
esac
|
||||
|
||||
# Packaging runs in a vanilla distro image, so the tooling comes from the distro's
|
||||
# archive rather than from nixpkgs:
|
||||
#
|
||||
# - debhelper and dpkg-dev build the DEB
|
||||
# - rpm-build builds the RPM, with systemd-rpm-macros and redhat-rpm-config
|
||||
# supplying the systemd and find-debuginfo macros the spec uses
|
||||
# - rpm-sign signs the built RPM
|
||||
# - git gives build_pkg.sh a real history to read SOURCE_DATE_EPOCH from;
|
||||
# without one the timestamp falls back to the wall clock
|
||||
# - curl uploads the finished packages in publish_pkg.sh
|
||||
# - ca-certificates lets curl and git verify TLS
|
||||
function install() {
|
||||
case "${ID}" in
|
||||
debian | ubuntu)
|
||||
apt-get update -y
|
||||
apt-get install -y --no-install-recommends \
|
||||
ca-certificates \
|
||||
curl \
|
||||
debhelper \
|
||||
debhelper-compat \
|
||||
dpkg-dev \
|
||||
@@ -48,10 +36,8 @@ function install() {
|
||||
|
||||
rhel | centos | rocky | almalinux)
|
||||
dnf install -y --setopt=install_weak_deps=False \
|
||||
curl-minimal \
|
||||
git \
|
||||
rpm-build \
|
||||
rpm-sign \
|
||||
redhat-rpm-config \
|
||||
systemd-rpm-macros
|
||||
;;
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Publish the DEB and RPM packages built by build_pkg.sh to the XRPLF package
|
||||
# repositories on Sonatype Nexus.
|
||||
#
|
||||
# Usage: publish_pkg.sh <channel> [package-dir]
|
||||
#
|
||||
# channel release channel, selecting the 'deb-<channel>' and
|
||||
# 'rpm-<channel>-hosted' repositories
|
||||
# package-dir searched recursively for *.deb, *.ddeb and *.rpm ('build' by
|
||||
# default)
|
||||
#
|
||||
# RPMs are uploaded to the hosted repository, but yum clients install from the
|
||||
# 'rpm-<channel>' group repository in front of it, which serves signed metadata.
|
||||
#
|
||||
# NEXUS_USERNAME and NEXUS_PASSWORD are required. NEXUS_URL overrides the target
|
||||
# instance, and DRY_RUN=1 lists the uploads without performing them.
|
||||
|
||||
channel="${1:-}"
|
||||
pkg_dir="${2:-build}"
|
||||
nexus_url="${NEXUS_URL:-https://packages.xrplf.org}"
|
||||
|
||||
if [[ -z "${channel}" ]]; then
|
||||
echo "usage: publish_pkg.sh <channel> [package-dir]" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
deb_repo="deb-${channel}"
|
||||
rpm_repo="rpm-${channel}-hosted"
|
||||
|
||||
if [[ -z "${DRY_RUN:-}" ]]; then
|
||||
: "${NEXUS_USERNAME:?is required}" "${NEXUS_PASSWORD:?is required}"
|
||||
fi
|
||||
|
||||
# Deliberate curl choices:
|
||||
#
|
||||
# - no --fail, which would hide the response body where Nexus explains what it
|
||||
# rejected
|
||||
# - no --location, since curl downgrades a redirected POST to GET and turns an
|
||||
# upload into a no-op that still answers 200
|
||||
# - credentials on stdin, to keep them out of the process list
|
||||
upload() {
|
||||
local url="$1"
|
||||
shift
|
||||
[[ -z "${DRY_RUN:-}" ]] || return 0
|
||||
|
||||
local body code status=0
|
||||
body="$(mktemp)"
|
||||
code="$(
|
||||
printf 'user = %s:%s\n' "${NEXUS_USERNAME}" "${NEXUS_PASSWORD}" |
|
||||
curl \
|
||||
--config - \
|
||||
--silent \
|
||||
--show-error \
|
||||
--retry 3 \
|
||||
--retry-delay 5 \
|
||||
--retry-all-errors \
|
||||
--output "${body}" \
|
||||
--write-out '%{http_code}' \
|
||||
"$@" \
|
||||
"${url}"
|
||||
)" || status=$?
|
||||
|
||||
if [[ ${status} -ne 0 || ! "${code}" =~ ^2[0-9][0-9]$ ]]; then
|
||||
echo "publish_pkg.sh: upload failed (curl ${status}, HTTP ${code}): ${url}" >&2
|
||||
cat "${body}" >&2
|
||||
echo >&2
|
||||
rm -f "${body}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -f "${body}"
|
||||
}
|
||||
|
||||
echo "Publishing ${pkg_dir} to ${deb_repo} and ${rpm_repo} on ${nexus_url}:"
|
||||
|
||||
count=0
|
||||
while IFS= read -r -d '' file; do
|
||||
name="${file##*/}"
|
||||
case "${name}" in
|
||||
# A raw body with a multipart Content-Type, POSTed to the repository root,
|
||||
# is the documented upload for a hosted apt repository:
|
||||
# https://help.sonatype.com/en/apt-repositories.html#deploying-packages-to-hosted-apt-repositories
|
||||
*.deb | *.ddeb)
|
||||
echo " ${name} -> ${deb_repo}"
|
||||
upload "${nexus_url}/repository/${deb_repo}/" \
|
||||
--header 'Content-Type: multipart/form-data' \
|
||||
--data-binary "@${file}"
|
||||
;;
|
||||
# yum repositories are addressed by path; the arch comes from the name.
|
||||
*.rpm)
|
||||
arch="${name%.rpm}"
|
||||
arch="${arch##*.}"
|
||||
echo " ${name} -> ${rpm_repo}/${arch}"
|
||||
upload "${nexus_url}/repository/${rpm_repo}/${arch}/${name}" \
|
||||
--upload-file "${file}"
|
||||
;;
|
||||
esac
|
||||
count=$((count + 1))
|
||||
done < <(find "${pkg_dir}" -type f \( -name '*.deb' -o -name '*.ddeb' -o -name '*.rpm' \) -print0)
|
||||
|
||||
# Uploading nothing would otherwise look like a successful publish.
|
||||
if [[ ${count} -eq 0 ]]; then
|
||||
echo "publish_pkg.sh: no packages found in ${pkg_dir}." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "${count} package(s) ${DRY_RUN:+would be }published."
|
||||
@@ -19,10 +19,8 @@ BuildRequires: systemd-rpm-macros
|
||||
|
||||
%undefine _debugsource_packages
|
||||
%debug_package
|
||||
# Level 3 rather than the el9 default of 19: it shrinks the multi-gigabyte
|
||||
# debuginfo package roughly fourfold in about a second, where 19 would spend
|
||||
# minutes on it.
|
||||
%global _binary_payload w3.zstdio
|
||||
# Intentionally trade larger RPM artifacts for faster package validation.
|
||||
%global _binary_payload w.ufdio
|
||||
%global _find_debuginfo_dwz_opts %{nil}
|
||||
|
||||
%build_mtime_policy clamp_to_source_date_epoch
|
||||
|
||||
@@ -24,5 +24,9 @@ LogsDirectoryMode=0750
|
||||
LimitNOFILE=65536
|
||||
SystemCallArchitectures=native
|
||||
|
||||
# Uncomment both lines to allow xrpld to bind to privileged ports (<1024)
|
||||
#CapabilityBoundingSet=CAP_NET_BIND_SERVICE
|
||||
#AmbientCapabilities=CAP_NET_BIND_SERVICE
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Sign the RPMs built by build_pkg.sh. Nexus signs the yum repository metadata
|
||||
# (via the 'rpm-<channel>' group repository), but never the packages themselves,
|
||||
# so they carry their own signature. Clients verify the packages with gpgcheck=1
|
||||
# and the metadata with repo_gpgcheck=1.
|
||||
#
|
||||
# Usage: sign_rpm.sh [package-dir]
|
||||
#
|
||||
# package-dir searched recursively for *.rpm ('build' by default)
|
||||
#
|
||||
# PKG_SIGNING_KEY must hold an armoured PGP private key. It has no flag, to keep
|
||||
# the key out of the process list.
|
||||
#
|
||||
# The DEBs are deliberately not signed: embedded DEB signatures exist (debsigs),
|
||||
# but apt does not verify them by default and trusts the repository metadata,
|
||||
# which Nexus signs, instead.
|
||||
|
||||
pkg_dir="${1:-build}"
|
||||
|
||||
mapfile -d '' rpms < <(find "${pkg_dir}" -type f -name '*.rpm' -print0)
|
||||
|
||||
# Signing nothing would otherwise look like a successful signing.
|
||||
if [[ ${#rpms[@]} -eq 0 ]]; then
|
||||
echo "sign_rpm.sh: no RPMs found in ${pkg_dir}." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
: "${PKG_SIGNING_KEY:?is required}"
|
||||
|
||||
# Global, and expanded by the trap when it fires: the keyring holds an
|
||||
# unencrypted private key, so it must go even if signing fails.
|
||||
signing_home="$(mktemp -d)"
|
||||
trap 'rm -rf "${signing_home}"' EXIT
|
||||
export GNUPGHOME="${signing_home}"
|
||||
|
||||
printf '%s' "${PKG_SIGNING_KEY}" | gpg --batch --quiet --import
|
||||
|
||||
# Exactly one secret key, so that picking the first below is not a guess between
|
||||
# several.
|
||||
secrets="$(gpg --list-secret-keys --with-colons | grep -c '^sec:' || true)"
|
||||
if [[ "${secrets}" -ne 1 ]]; then
|
||||
echo "sign_rpm.sh: PKG_SIGNING_KEY must hold exactly one secret key, found ${secrets}." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
key="$(gpg --list-secret-keys --with-colons | awk -F: '/^fpr:/ { print $10; exit }')"
|
||||
echo "Signing ${#rpms[@]} RPM(s) with ${key}."
|
||||
|
||||
# Loopback pinentry: the key is unattended, so there is no tty to prompt on.
|
||||
rpmsign \
|
||||
--define "_gpg_name ${key}" \
|
||||
--define "_gpg_sign_cmd_extra_args --pinentry-mode loopback --batch --yes" \
|
||||
--addsign "${rpms[@]}"
|
||||
|
||||
# rpmsign can exit 0 having attached nothing, and an unsigned package is only
|
||||
# rejected later, on the installing machine. Both header tags are checked
|
||||
# because an RSA signature lands in RSAHEADER and a DSA or EdDSA one in
|
||||
# DSAHEADER.
|
||||
for pkg in "${rpms[@]}"; do
|
||||
signature="$(rpm --query --queryformat '%{RSAHEADER:pgpsig}%{DSAHEADER:pgpsig}' --package "${pkg}")"
|
||||
if [[ "${signature}" == "(none)(none)" ]]; then
|
||||
echo "sign_rpm.sh: ${pkg} is unsigned after rpmsign." >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
@@ -223,6 +223,11 @@ class Number::Guard
|
||||
std::uint8_t sbit_ : 1 {0}; // the sign of the guard digits
|
||||
|
||||
public:
|
||||
// Decimal digits held in digits_, four bits each. After this many zero
|
||||
// pushes digits_ holds only zeros and xbit_ has absorbed everything shifted
|
||||
// off, so further pushes of zeros leave the Guard unchanged.
|
||||
static constexpr int kGuardDigits = 8 * sizeof(digits_) / 4;
|
||||
|
||||
internalrep const minMantissa;
|
||||
internalrep const maxMantissa;
|
||||
MantissaRange::CuspRoundingFix const cuspRoundingFix;
|
||||
@@ -277,6 +282,18 @@ public:
|
||||
void
|
||||
doDropDigit(T& mantissa, int& exponent) noexcept;
|
||||
|
||||
/**
|
||||
* Drop digits from mantissa until the exponent increases to target. No-op if exponent is
|
||||
* greater or equal to target already.
|
||||
*
|
||||
* Once the mantissa reaches zero every further drop pushes a zero digit, and this Guard stops
|
||||
* changing after kGuardDigits of those. The rest of the drops would only advance the exponent,
|
||||
* so jump it instead, to save at most 32768 * 2 - 35 loops.
|
||||
*/
|
||||
template <class T>
|
||||
void
|
||||
dropDigitsTo(T& mantissa, int& exponent, int target) noexcept;
|
||||
|
||||
// Modify the result to the correctly rounded value
|
||||
template <UnsignedMantissa T>
|
||||
void
|
||||
@@ -401,6 +418,23 @@ Number::Guard::doDropDigit<uint128_t>(uint128_t& mantissa, int& exponent) noexce
|
||||
++exponent;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void
|
||||
Number::Guard::dropDigitsTo(T& mantissa, int& exponent, int target) noexcept
|
||||
{
|
||||
while (exponent < target)
|
||||
{
|
||||
if (mantissa == 0)
|
||||
{
|
||||
for (int i = 0; i < kGuardDigits && exponent < target; ++i)
|
||||
doDropDigit(mantissa, exponent);
|
||||
exponent = target;
|
||||
return;
|
||||
}
|
||||
doDropDigit(mantissa, exponent);
|
||||
}
|
||||
}
|
||||
|
||||
template <UnsignedMantissa T>
|
||||
void
|
||||
Number::Guard::pushOverflow(T mantissa)
|
||||
@@ -933,6 +967,8 @@ Number::operator+=(Number const& y)
|
||||
{
|
||||
// For Enabled330, there are three steps.
|
||||
// 1. First, shrink the mantissa of shrinkM/shrinkE while shrinkM ends in 0.
|
||||
// Bounded by the mantissa, not the exponent: shrinkM is non-zero and normalized,
|
||||
// so its leading digit is non-zero and stops the loop within 18 iterations.
|
||||
while (shrinkE < expandE && shrinkM % 10 == 0)
|
||||
{
|
||||
g.doDropDigit(shrinkM, shrinkE);
|
||||
@@ -950,10 +986,7 @@ Number::operator+=(Number const& y)
|
||||
|
||||
// 3. Finally, shrink the mantissa of shrinkM/shrinkE until the exponents match. Any removed
|
||||
// digits will be put into the Guard. This is the only step for non-Enabled330 modes.
|
||||
while (shrinkE < expandE)
|
||||
{
|
||||
g.doDropDigit(shrinkM, shrinkE);
|
||||
}
|
||||
g.dropDigitsTo(shrinkM, shrinkE, expandE);
|
||||
};
|
||||
|
||||
// Shrink the mantissa and raise the exponent of the value with the lower exponent. Store any
|
||||
@@ -1330,10 +1363,7 @@ operator rep() const
|
||||
g.setNegative();
|
||||
drops = -drops;
|
||||
}
|
||||
while (offset < 0)
|
||||
{
|
||||
g.doDropDigit(drops, offset);
|
||||
}
|
||||
g.dropDigitsTo(drops, offset, 0);
|
||||
for (; offset > 0; --offset)
|
||||
{
|
||||
if (drops > kMaxRep / 10)
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include <set> // IWYU pragma: keep
|
||||
#include <stack>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@@ -88,14 +87,14 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
output(std::string_view bytes)
|
||||
output(boost::beast::string_view const& bytes)
|
||||
{
|
||||
markStarted();
|
||||
output_(bytes);
|
||||
}
|
||||
|
||||
void
|
||||
stringOutput(std::string_view bytes)
|
||||
stringOutput(boost::beast::string_view const& bytes)
|
||||
{
|
||||
markStarted();
|
||||
std::size_t position = 0, writtenUntil = 0;
|
||||
|
||||
@@ -61,10 +61,12 @@ hasExpired(
|
||||
: view.parentCloseTime() > boundary;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
std::optional<bool>
|
||||
checkVaultPseudoAccountFrozenPreconditions(ReadView const& view, std::uint8_t depth)
|
||||
bool
|
||||
isVaultPseudoAccountFrozen(
|
||||
ReadView const& view,
|
||||
AccountID const& account,
|
||||
MPTIssue const& mptShare,
|
||||
std::uint8_t depth)
|
||||
{
|
||||
if (!view.rules().enabled(featureSingleAssetVault))
|
||||
return false;
|
||||
@@ -72,37 +74,26 @@ checkVaultPseudoAccountFrozenPreconditions(ReadView const& view, std::uint8_t de
|
||||
if (depth >= kMaxAssetCheckDepth)
|
||||
{
|
||||
// LCOV_EXCL_START
|
||||
UNREACHABLE(
|
||||
"xrpl::View::checkVaultPseudoAccountFrozenPreconditions : reached asset check depth");
|
||||
UNREACHABLE("xrpl::View::isVaultPseudoAccountFrozen : reached asset check depth");
|
||||
return true;
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
auto const mptIssuance = view.read(keylet::mptokenIssuance(mptShare.getMptID()));
|
||||
if (mptIssuance == nullptr)
|
||||
return false; // zero MPToken won't block deletion of MPTokenIssuance
|
||||
|
||||
bool
|
||||
isVaultPseudoAccountFrozenForIssuance(
|
||||
ReadView const& view,
|
||||
AccountID const& account,
|
||||
SLE const& issuanceSle,
|
||||
std::uint8_t depth)
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
issuanceSle.getType() == ltMPTOKEN_ISSUANCE,
|
||||
"xrpl::isVaultPseudoAccountFrozenForIssuance : MPTokenIssuance SLE");
|
||||
|
||||
auto const issuer = issuanceSle.getAccountID(sfIssuer);
|
||||
auto const issuer = mptIssuance->getAccountID(sfIssuer);
|
||||
|
||||
// Post-fixCleanup3_2_0: vault shares carry sfReferenceHolding pointing
|
||||
// to the vault pseudo's MPToken or RippleState for the underlying.
|
||||
// Read it to derive the underlying asset and recurse, skipping the
|
||||
// issuer-account-then-vault chain. Pre-amendment shares (no field)
|
||||
// fall back to the chain lookup below.
|
||||
if (issuanceSle.isFieldPresent(sfReferenceHolding))
|
||||
if (mptIssuance->isFieldPresent(sfReferenceHolding))
|
||||
{
|
||||
auto const sleHolding =
|
||||
view.read(keylet::unchecked(issuanceSle.getFieldH256(sfReferenceHolding)));
|
||||
view.read(keylet::unchecked(mptIssuance->getFieldH256(sfReferenceHolding)));
|
||||
if (!sleHolding)
|
||||
{
|
||||
// LCOV_EXCL_START
|
||||
@@ -111,7 +102,7 @@ isVaultPseudoAccountFrozenForIssuance(
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
return isAnyFrozen(
|
||||
view, {issuer, account}, assetOfHolding(issuanceSle, *sleHolding), depth + 1);
|
||||
view, {issuer, account}, assetOfHolding(*mptIssuance, *sleHolding), depth + 1);
|
||||
}
|
||||
|
||||
auto const mptIssuer = view.read(keylet::account(issuer));
|
||||
@@ -137,38 +128,6 @@ isVaultPseudoAccountFrozenForIssuance(
|
||||
return isAnyFrozen(view, {issuer, account}, vault->at(sfAsset), depth + 1);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool
|
||||
isVaultPseudoAccountFrozen(
|
||||
ReadView const& view,
|
||||
AccountID const& account,
|
||||
SLE const& issuanceSle,
|
||||
std::uint8_t depth)
|
||||
{
|
||||
if (auto const result = checkVaultPseudoAccountFrozenPreconditions(view, depth))
|
||||
return *result;
|
||||
|
||||
return isVaultPseudoAccountFrozenForIssuance(view, account, issuanceSle, depth);
|
||||
}
|
||||
|
||||
bool
|
||||
isVaultPseudoAccountFrozen(
|
||||
ReadView const& view,
|
||||
AccountID const& account,
|
||||
MPTIssue const& mptShare,
|
||||
std::uint8_t depth)
|
||||
{
|
||||
if (auto const result = checkVaultPseudoAccountFrozenPreconditions(view, depth))
|
||||
return *result;
|
||||
|
||||
auto const issuanceSle = view.read(keylet::mptokenIssuance(mptShare.getMptID()));
|
||||
if (issuanceSle == nullptr)
|
||||
return false; // zero MPToken won't block deletion of MPTokenIssuance
|
||||
|
||||
return isVaultPseudoAccountFrozenForIssuance(view, account, *issuanceSle, depth);
|
||||
}
|
||||
|
||||
bool
|
||||
isLPTokenFrozen(
|
||||
ReadView const& view,
|
||||
@@ -179,33 +138,6 @@ isLPTokenFrozen(
|
||||
return isFrozen(view, account, asset) || isFrozen(view, account, asset2);
|
||||
}
|
||||
|
||||
TER
|
||||
canTransferLPToken(
|
||||
ReadView const& view,
|
||||
AccountID const& from,
|
||||
AccountID const& to,
|
||||
AccountID const& lpTokenIssuer)
|
||||
{
|
||||
// Only AMM-issued LPTokens are subject to this check. The LPToken's issuer
|
||||
// is the AMM account; if it is not an AMM, this is not an LPToken.
|
||||
auto const sleIssuer = view.read(keylet::account(lpTokenIssuer));
|
||||
if (!sleIssuer || !sleIssuer->isFieldPresent(sfAMMID))
|
||||
return tesSUCCESS;
|
||||
|
||||
auto const sleAmm = view.read(keylet::amm((*sleIssuer)[sfAMMID]));
|
||||
if (!sleAmm)
|
||||
return tecINTERNAL; // LCOV_EXCL_LINE
|
||||
|
||||
auto const transferable = [&](Asset const& a) -> TER {
|
||||
if (!a.holds<MPTIssue>())
|
||||
return tesSUCCESS;
|
||||
return canTransfer(view, a.get<MPTIssue>(), from, to);
|
||||
};
|
||||
if (auto const err = transferable((*sleAmm)[sfAsset]); !isTesSuccess(err))
|
||||
return err;
|
||||
return transferable((*sleAmm)[sfAsset2]);
|
||||
}
|
||||
|
||||
bool
|
||||
areCompatible(
|
||||
ReadView const& validLedger,
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/ledger/Sandbox.h>
|
||||
#include <xrpl/ledger/View.h>
|
||||
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
|
||||
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
|
||||
#include <xrpl/ledger/helpers/TokenHelpers.h>
|
||||
#include <xrpl/protocol/AMMCore.h>
|
||||
@@ -634,7 +633,7 @@ ammAccountHolds(ReadView const& view, AccountID const& ammAccountID, Asset const
|
||||
return asset.visit(
|
||||
[&](MPTIssue const& issue) {
|
||||
if (auto const sle = view.read(keylet::mptoken(issue, ammAccountID));
|
||||
sle && !isFrozen(view, ammAccountID, *sle))
|
||||
sle && !isFrozen(view, ammAccountID, issue))
|
||||
return STAmount{issue, (*sle)[sfMPTAmount]};
|
||||
return STAmount{asset};
|
||||
},
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include <xrpl/ledger/helpers/VaultHelpers.h>
|
||||
#include <xrpl/protocol/Asset.h>
|
||||
#include <xrpl/protocol/Feature.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/LedgerFormats.h>
|
||||
#include <xrpl/protocol/Protocol.h>
|
||||
#include <xrpl/protocol/Rules.h>
|
||||
@@ -21,15 +20,12 @@
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/protocol/TxFlags.h>
|
||||
#include <xrpl/protocol/TxFormats.h>
|
||||
#include <xrpl/protocol/Units.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
@@ -81,40 +77,6 @@ checkLendingProtocolDependencies(Rules const& rules, STTx const& tx)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<LoanDefaultFreezeExemptAccounts>
|
||||
getLoanDefaultFreezeExemptAccounts(ReadView const& view, STTx const& tx)
|
||||
{
|
||||
if (tx.getTxnType() != ttLOAN_MANAGE || !tx.isFlag(tfLoanDefault) ||
|
||||
!view.rules().enabled(fixCleanup3_4_0))
|
||||
return std::nullopt;
|
||||
|
||||
// Unlike the broker/vault lookups below, the submitter picks the LoanID,
|
||||
// so a nonexistent Loan is an ordinary (if unusual) input, not a
|
||||
// structural impossibility -- exercised directly in LendingHelpers_test.
|
||||
auto const loanSle = view.read(keylet::loan(tx[sfLoanID]));
|
||||
if (!loanSle)
|
||||
return std::nullopt;
|
||||
|
||||
// A Loan can't outlive its LoanBroker (LoanBrokerDelete's preclaim
|
||||
// rejects deletion while DebtTotal != 0), and a LoanBroker can't outlive
|
||||
// its Vault (VaultDelete's preclaim has the equivalent guard) -- so these
|
||||
// two lookups are structurally guaranteed to succeed here.
|
||||
auto const brokerSle = view.read(keylet::loanBroker(loanSle->at(sfLoanBrokerID)));
|
||||
if (!brokerSle)
|
||||
return std::nullopt; // LCOV_EXCL_LINE
|
||||
|
||||
auto const vaultSle = view.read(keylet::vault(brokerSle->at(sfVaultID)));
|
||||
if (!vaultSle)
|
||||
return std::nullopt; // LCOV_EXCL_LINE
|
||||
|
||||
Asset const vaultAsset = vaultSle->at(sfAsset);
|
||||
return LoanDefaultFreezeExemptAccounts{
|
||||
.issuer = vaultAsset.getIssuer(),
|
||||
.broker = brokerSle->at(sfAccount),
|
||||
.vault = vaultSle->at(sfAccount),
|
||||
.asset = vaultAsset};
|
||||
}
|
||||
|
||||
LoanPaymentParts&
|
||||
LoanPaymentParts::operator+=(LoanPaymentParts const& other)
|
||||
{
|
||||
|
||||
@@ -42,35 +42,18 @@ bool
|
||||
isGlobalFrozen(ReadView const& view, MPTIssue const& mptIssue)
|
||||
{
|
||||
if (auto const sle = view.read(keylet::mptokenIssuance(mptIssue.getMptID())))
|
||||
return isGlobalFrozen(*sle);
|
||||
return sle->isFlag(lsfMPTLocked);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
isGlobalFrozen(SLE const& issuanceSle)
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
issuanceSle.getType() == ltMPTOKEN_ISSUANCE, "xrpl::isGlobalFrozen : MPTokenIssuance SLE");
|
||||
|
||||
return issuanceSle.isFlag(lsfMPTLocked);
|
||||
}
|
||||
|
||||
bool
|
||||
isIndividualFrozen(ReadView const& view, AccountID const& account, MPTIssue const& mptIssue)
|
||||
{
|
||||
if (auto const sle = view.read(keylet::mptoken(mptIssue.getMptID(), account)))
|
||||
return isIndividualFrozen(*sle);
|
||||
return sle->isFlag(lsfMPTLocked);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
isIndividualFrozen(SLE const& mptSle)
|
||||
{
|
||||
XRPL_ASSERT(mptSle.getType() == ltMPTOKEN, "xrpl::isIndividualFrozen : MPToken SLE");
|
||||
|
||||
return mptSle.isFlag(lsfMPTLocked);
|
||||
}
|
||||
|
||||
bool
|
||||
isFrozen(
|
||||
ReadView const& view,
|
||||
@@ -82,34 +65,6 @@ isFrozen(
|
||||
isVaultPseudoAccountFrozen(view, account, mptIssue, depth);
|
||||
}
|
||||
|
||||
bool
|
||||
isFrozen(ReadView const& view, AccountID const& account, SLE const& sle, std::uint8_t depth)
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
sle.getType() == ltMPTOKEN || sle.getType() == ltMPTOKEN_ISSUANCE,
|
||||
"xrpl::isFrozen : MPToken or MPTokenIssuance SLE");
|
||||
|
||||
if (sle.getType() == ltMPTOKEN)
|
||||
{
|
||||
XRPL_ASSERT(sle[sfAccount] == account, "xrpl::isFrozen : valid MPToken holder");
|
||||
|
||||
MPTID const mptID = sle[sfMPTokenIssuanceID];
|
||||
auto const issuanceSle = view.read(keylet::mptokenIssuance(mptID));
|
||||
|
||||
if ((issuanceSle && isGlobalFrozen(*issuanceSle)) || isIndividualFrozen(sle))
|
||||
return true;
|
||||
|
||||
if (issuanceSle)
|
||||
return isVaultPseudoAccountFrozen(view, account, *issuanceSle, depth);
|
||||
|
||||
return isVaultPseudoAccountFrozen(view, account, MPTIssue{mptID}, depth);
|
||||
}
|
||||
|
||||
MPTIssue const mptIssue{sle[sfSequence], sle[sfIssuer]};
|
||||
return isGlobalFrozen(sle) || isIndividualFrozen(view, account, mptIssue) ||
|
||||
isVaultPseudoAccountFrozen(view, account, sle, depth);
|
||||
}
|
||||
|
||||
[[nodiscard]] bool
|
||||
isAnyFrozen(
|
||||
ReadView const& view,
|
||||
@@ -117,8 +72,7 @@ isAnyFrozen(
|
||||
MPTIssue const& mptIssue,
|
||||
std::uint8_t depth)
|
||||
{
|
||||
auto const issuanceSle = view.read(keylet::mptokenIssuance(mptIssue.getMptID()));
|
||||
if (issuanceSle && isGlobalFrozen(*issuanceSle))
|
||||
if (isGlobalFrozen(view, mptIssue))
|
||||
return true;
|
||||
|
||||
for (auto const& account : accounts)
|
||||
@@ -127,15 +81,9 @@ isAnyFrozen(
|
||||
return true;
|
||||
}
|
||||
|
||||
// Pass the issuance SLE when we have it to avoid re-reading it per account;
|
||||
// otherwise defer to the MPTIssue overload, which handles a missing issuance.
|
||||
auto const anyVaultFrozen = [&](auto const& shareOrIssuance) {
|
||||
return std::ranges::any_of(accounts, [&](auto const& account) {
|
||||
return isVaultPseudoAccountFrozen(view, account, shareOrIssuance, depth);
|
||||
});
|
||||
};
|
||||
|
||||
return issuanceSle ? anyVaultFrozen(*issuanceSle) : anyVaultFrozen(mptIssue);
|
||||
return std::ranges::any_of(accounts, [&](auto const& account) {
|
||||
return isVaultPseudoAccountFrozen(view, account, mptIssue, depth);
|
||||
});
|
||||
}
|
||||
|
||||
Rate
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user