Compare commits

...

28 Commits

Author SHA1 Message Date
JCW
9250be0f28 Fix error 2026-06-16 15:39:54 +01:00
JCW
933dfc0386 Update pipeline and conan to use vs2026 and grpc 1.81.0 2026-06-16 15:28:24 +01:00
Ayaz Salikhov
0364e4dc41 docs: Rewrite build environment docs (#7533)
Co-authored-by: Ed Hennis <ed@ripple.com>
2026-06-16 13:24:12 +00:00
Pratik Mankawde
2df96b1550 fix: Silence UBSan diagnostics in the ubsan build config (#7531)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 19:25:37 +00:00
Ayaz Salikhov
fe4c8ae82a build: Add ClangBuildAnalyzer to Nix (#7538)
Co-authored-by: Bart <bthomee@users.noreply.github.com>
2026-06-15 19:04:33 +00:00
Zhiyuan Wang
b34aa84e5a fix: Check Fee-Free Division by Zero in AMMWithdraw singleWithdrawEPrice (#6989) 2026-06-15 15:31:22 +00:00
Bart
f5985e73ec fix: Always charge peer on strand (#7422)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
2026-06-15 14:55:56 +00:00
Sergey Kuznetsov
4387aac1a5 chore: Remove conan patch in nix (#7534) 2026-06-15 14:55:43 +00:00
Pratik Mankawde
df395d6851 test: Add null check unit test for Oracle::aggregatePrice (#7306)
Signed-off-by: Pratik Mankawde <3397372+pratikmankawde@users.noreply.github.com>
2026-06-11 18:05:36 +00:00
Ayaz Salikhov
8e618d68cd ci: Patch conan recipe for Nix to be able to use on macOS (#7532) 2026-06-11 17:36:33 +00:00
Ayaz Salikhov
cee157485e ci: Run sanitizers on release builds too (#7527) 2026-06-11 12:59:22 +00:00
Zhiyuan Wang
09c36d066e fix: Correct hybrid offer deletion on credential expiry (#6843)
Co-authored-by: Bart <bthomee@users.noreply.github.com>
2026-06-10 20:42:41 +00:00
Ayaz Salikhov
2f6b466feb ci: Make sanitizer flags lists in the profile, not a string (#7449) 2026-06-10 18:24:34 +00:00
Ayaz Salikhov
8000adfa79 ci: Make configurations launch on certain event types (#7447) 2026-06-10 18:08:34 +00:00
Shi Cheng
1f359f719c fix: Add [[maybe_unused]] to fix320Enabled for assert=OFF builds (#7446)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 17:24:44 +00:00
Ayaz Salikhov
dd0b6754d4 ci: Add gh and file to nix packages (#7444) 2026-06-10 14:45:51 +00:00
Vito Tumas
83cc5df72e fix: Disable transaction invariants (#7409) 2026-06-10 12:05:53 +00:00
Vito Tumas
97ca7d57bc perf: Dispatch "hasInvalidAmount()" on type tag instead of dynamic_cast (#7402) 2026-06-10 11:44:57 +00:00
Pratik Mankawde
8a4bf2dee6 refactor: Retire fixUniversalNumber amendment (#5962)
Signed-off-by: Pratik Mankawde <pmankawde@ripple.com>
Signed-off-by: Pratik Mankawde <3397372+pratikmankawde@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-10 10:16:03 +00:00
Bart
742aa0878b test: Do not create data directory for memory databases (#7323)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
2026-06-10 09:16:53 +00:00
Ayaz Salikhov
8617eaeb26 ci: Launch upload-conan-deps on profile change (#7442) 2026-06-10 00:00:19 +00:00
Ed Hennis
2cbc3c139e fix: Fix Number comparison operator (#7406) 2026-06-09 17:46:56 +00:00
Ayaz Salikhov
fccb109e48 feat: Use C++ 23 standard (#7431) 2026-06-09 17:36:17 +00:00
Vito Tumas
0fb1aca461 refactor: Introduce XRPL_ASSERT_IF for amendment-gated assertions (#7378)
Co-authored-by: xrplf-ai-reviewer[bot] <266832837+xrplf-ai-reviewer[bot]@users.noreply.github.com>
2026-06-09 17:02:06 +00:00
Bart
c552eb333f refactor: Change config section and key string literals into constants (#7095)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
2026-06-09 14:58:21 +00:00
Bart
c9769d1add refactor: Use std::move and std::string_view where possible (#7424)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
2026-06-09 13:56:32 +00:00
Bart
ee9fbc4e08 refactor: Use const function arguments where possible (#7423)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
2026-06-09 10:04:09 +00:00
Ayaz Salikhov
577d7457f1 ci: Use XRPLF/actions build-multiarch-image workflow (#7428) 2026-06-08 17:10:05 +00:00
239 changed files with 3613 additions and 3617 deletions

View File

@@ -153,7 +153,7 @@ Checks: "-*,
readability-use-std-min-max
"
# ---
# readability-inconsistent-declaration-parameter-name, # in this codebase this check will break a lot of arg names
# readability-inconsistent-declaration-parameter-name, # In this codebase this check will break a lot of arg names
# readability-static-accessed-through-instance, # this check is probably unnecessary. It makes the code less readable
# ---

View File

@@ -1,6 +1,8 @@
libxrpl.basics > xrpl.basics
libxrpl.conditions > xrpl.basics
libxrpl.conditions > xrpl.conditions
libxrpl.config > xrpl.basics
libxrpl.config > xrpl.config
libxrpl.core > xrpl.basics
libxrpl.core > xrpl.core
libxrpl.core > xrpl.json
@@ -17,6 +19,7 @@ libxrpl.ledger > xrpl.shamap
libxrpl.net > xrpl.basics
libxrpl.net > xrpl.net
libxrpl.nodestore > xrpl.basics
libxrpl.nodestore > xrpl.config
libxrpl.nodestore > xrpl.json
libxrpl.nodestore > xrpl.nodestore
libxrpl.nodestore > xrpl.protocol
@@ -24,6 +27,7 @@ libxrpl.protocol > xrpl.basics
libxrpl.protocol > xrpl.json
libxrpl.protocol > xrpl.protocol
libxrpl.rdb > xrpl.basics
libxrpl.rdb > xrpl.config
libxrpl.rdb > xrpl.core
libxrpl.rdb > xrpl.rdb
libxrpl.resource > xrpl.basics
@@ -31,6 +35,7 @@ libxrpl.resource > xrpl.json
libxrpl.resource > xrpl.protocol
libxrpl.resource > xrpl.resource
libxrpl.server > xrpl.basics
libxrpl.server > xrpl.config
libxrpl.server > xrpl.core
libxrpl.server > xrpl.json
libxrpl.server > xrpl.protocol
@@ -52,6 +57,7 @@ libxrpl.tx > xrpl.tx
test.app > test.jtx
test.app > test.unit_test
test.app > xrpl.basics
test.app > xrpl.config
test.app > xrpl.core
test.app > xrpld.app
test.app > xrpld.consensus
@@ -90,6 +96,7 @@ test.consensus > xrpl.tx
test.core > test.jtx
test.core > test.unit_test
test.core > xrpl.basics
test.core > xrpl.config
test.core > xrpl.core
test.core > xrpld.core
test.core > xrpl.json
@@ -104,6 +111,7 @@ test.csf > xrpl.protocol
test.json > test.jtx
test.json > xrpl.json
test.jtx > xrpl.basics
test.jtx > xrpl.config
test.jtx > xrpl.core
test.jtx > xrpld.app
test.jtx > xrpld.core
@@ -126,6 +134,7 @@ test.ledger > xrpl.protocol
test.nodestore > test.jtx
test.nodestore > test.unit_test
test.nodestore > xrpl.basics
test.nodestore > xrpl.config
test.nodestore > xrpld.core
test.nodestore > xrpl.nodestore
test.nodestore > xrpl.protocol
@@ -133,6 +142,7 @@ test.nodestore > xrpl.rdb
test.overlay > test.jtx
test.overlay > test.unit_test
test.overlay > xrpl.basics
test.overlay > xrpl.config
test.overlay > xrpld.app
test.overlay > xrpld.core
test.overlay > xrpld.overlay
@@ -159,6 +169,7 @@ test.resource > xrpl.basics
test.resource > xrpl.resource
test.rpc > test.jtx
test.rpc > xrpl.basics
test.rpc > xrpl.config
test.rpc > xrpl.core
test.rpc > xrpld.app
test.rpc > xrpld.core
@@ -173,6 +184,7 @@ test.rpc > xrpl.tx
test.server > test.jtx
test.server > test.unit_test
test.server > xrpl.basics
test.server > xrpl.config
test.server > xrpld.app
test.server > xrpld.core
test.server > xrpl.json
@@ -180,6 +192,7 @@ test.server > xrpl.protocol
test.server > xrpl.server
test.shamap > test.unit_test
test.shamap > xrpl.basics
test.shamap > xrpl.config
test.shamap > xrpl.nodestore
test.shamap > xrpl.protocol
test.shamap > xrpl.shamap
@@ -188,6 +201,7 @@ test.toplevel > xrpl.json
test.unit_test > xrpl.basics
test.unit_test > xrpl.protocol
tests.libxrpl > xrpl.basics
tests.libxrpl > xrpl.config
tests.libxrpl > xrpl.core
tests.libxrpl > xrpl.json
tests.libxrpl > xrpl.ledger
@@ -200,6 +214,7 @@ tests.libxrpl > xrpl.shamap
tests.libxrpl > xrpl.tx
xrpl.conditions > xrpl.basics
xrpl.conditions > xrpl.protocol
xrpl.config > xrpl.basics
xrpl.core > xrpl.basics
xrpl.core > xrpl.json
xrpl.core > xrpl.protocol
@@ -210,6 +225,7 @@ xrpl.ledger > xrpl.server
xrpl.ledger > xrpl.shamap
xrpl.net > xrpl.basics
xrpl.nodestore > xrpl.basics
xrpl.nodestore > xrpl.config
xrpl.nodestore > xrpl.protocol
xrpl.protocol > xrpl.basics
xrpl.protocol > xrpl.json
@@ -237,6 +253,7 @@ xrpl.tx > xrpl.ledger
xrpl.tx > xrpl.protocol
xrpld.app > test.unit_test
xrpld.app > xrpl.basics
xrpld.app > xrpl.config
xrpld.app > xrpl.core
xrpld.app > xrpld.consensus
xrpld.app > xrpld.core
@@ -255,11 +272,13 @@ xrpld.consensus > xrpl.json
xrpld.consensus > xrpl.ledger
xrpld.consensus > xrpl.protocol
xrpld.core > xrpl.basics
xrpld.core > xrpl.config
xrpld.core > xrpl.core
xrpld.core > xrpl.net
xrpld.core > xrpl.protocol
xrpld.core > xrpl.rdb
xrpld.overlay > xrpl.basics
xrpld.overlay > xrpl.config
xrpld.overlay > xrpl.core
xrpld.overlay > xrpld.consensus
xrpld.overlay > xrpld.core
@@ -272,15 +291,18 @@ xrpld.overlay > xrpl.server
xrpld.overlay > xrpl.shamap
xrpld.overlay > xrpl.tx
xrpld.peerfinder > xrpl.basics
xrpld.peerfinder > xrpl.config
xrpld.peerfinder > xrpld.core
xrpld.peerfinder > xrpl.protocol
xrpld.peerfinder > xrpl.rdb
xrpld.perflog > xrpl.basics
xrpld.perflog > xrpl.config
xrpld.perflog > xrpl.core
xrpld.perflog > xrpld.rpc
xrpld.perflog > xrpl.json
xrpld.perflog > xrpl.protocol
xrpld.rpc > xrpl.basics
xrpld.rpc > xrpl.config
xrpld.rpc > xrpl.core
xrpld.rpc > xrpld.core
xrpld.rpc > xrpl.json

View File

@@ -27,6 +27,19 @@ def get_cmake_args(build_type: str, extra_args: str) -> str:
return " ".join(args)
def runs_on_event(exclude_event_types: list[str], event: str | None) -> bool:
"""Whether a config should run for the current event.
'exclude_event_types' is a list of GitHub event names (e.g.
["pull_request"]) on which the config should NOT run; an empty list means
the config runs on every event. When no event is given (event is None), no
filtering is applied.
"""
if event is None:
return True
return event not in exclude_event_types
# ---------------------------------------------------------------------------
# Input types — shapes of the JSON config files
# ---------------------------------------------------------------------------
@@ -43,6 +56,9 @@ class LinuxConfig:
suffix: str = ""
extra_cmake_args: str = ""
image: str = "" # only used by package_configs entries
# List of GitHub event names (e.g. "pull_request") on which this config
# should NOT run. Empty means it runs on every event.
exclude_event_types: list[str] = dataclasses.field(default_factory=list)
@dataclasses.dataclass
@@ -77,6 +93,9 @@ class PlatformConfig:
build_type: list[str]
build_only: bool = False # if true, skip tests (e.g. macos/Windows Debug)
extra_cmake_args: str = ""
# List of GitHub event names (e.g. "pull_request") on which this config
# should NOT run. Empty means it runs on every event.
exclude_event_types: list[str] = dataclasses.field(default_factory=list)
def __post_init__(self) -> None:
if isinstance(self.build_type, str):
@@ -151,16 +170,21 @@ _ARCHS: dict[str, Architecture] = {
}
def expand_linux_matrix(linux: LinuxFile) -> list[MatrixEntry]:
def expand_linux_matrix(
linux: LinuxFile, event: str | None = None
) -> list[MatrixEntry]:
"""Expand a LinuxFile into a flat list of matrix entries.
Each config entry is expanded over the cross-product of its
compiler, build_type, sanitizers, and architecture lists.
compiler, build_type, sanitizers, and architecture lists. Configs that
exclude the current event are skipped.
"""
entries: list[MatrixEntry] = []
for distro, configs in linux.configs.items():
for cfg in configs:
if not runs_on_event(cfg.exclude_event_types, event):
continue
# An empty sanitizers list means "one entry with no sanitizer".
effective_sanitizers = cfg.sanitizers or [""]
effective_archs = {arch: _ARCHS[arch] for arch in cfg.arch}
@@ -218,13 +242,20 @@ def expand_linux_packaging(linux: LinuxFile) -> list[PackagingEntry]:
return entries
def expand_platform_matrix(pf: PlatformFile) -> list[MatrixEntry]:
"""Expand a PlatformFile (macOS or Windows) into matrix entries."""
def expand_platform_matrix(
pf: PlatformFile, event: str | None = None
) -> list[MatrixEntry]:
"""Expand a PlatformFile (macOS or Windows) into matrix entries.
Configs that exclude the current event are skipped.
"""
platform_name, arch = pf.platform.split("/")
is_windows = platform_name == "windows"
entries: list[MatrixEntry] = []
for cfg in pf.configs:
if not runs_on_event(cfg.exclude_event_types, event):
continue
for build_type in cfg.build_type:
entries.append(
MatrixEntry(
@@ -262,6 +293,14 @@ if __name__ == "__main__":
help="Emit the Linux packaging matrix instead of the build/test matrix.",
action="store_true",
)
parser.add_argument(
"-e",
"--event",
help="The GitHub event name that triggered the workflow (e.g. 'push', "
"'pull_request'). Configs are filtered by their 'event_type'. If "
"omitted, no filtering is applied.",
default=None,
)
args = parser.parse_args()
matrix: list[MatrixEntry] | list[PackagingEntry] = []
@@ -270,12 +309,16 @@ if __name__ == "__main__":
matrix = expand_linux_packaging(LinuxFile.load(THIS_DIR / "linux.json"))
else:
if args.config in ("linux", None):
matrix += expand_linux_matrix(LinuxFile.load(THIS_DIR / "linux.json"))
matrix += expand_linux_matrix(
LinuxFile.load(THIS_DIR / "linux.json"), args.event
)
if args.config in ("macos", None):
matrix += expand_platform_matrix(PlatformFile.load(THIS_DIR / "macos.json"))
matrix += expand_platform_matrix(
PlatformFile.load(THIS_DIR / "macos.json"), args.event
)
if args.config in ("windows", None):
matrix += expand_platform_matrix(
PlatformFile.load(THIS_DIR / "windows.json")
PlatformFile.load(THIS_DIR / "windows.json"), args.event
)
print(f"matrix={json.dumps({'include': [dataclasses.asdict(e) for e in matrix]})}")

View File

@@ -1,5 +1,5 @@
{
"image_tag": "sha-63ffdc3",
"image_tag": "sha-fe4c8ae",
"configs": {
"ubuntu": [
{
@@ -10,7 +10,7 @@
{
"compiler": ["gcc", "clang"],
"build_type": ["Debug"],
"build_type": ["Debug", "Release"],
"arch": ["amd64"],
"sanitizers": ["address", "undefinedbehavior"]
},
@@ -41,7 +41,8 @@
"build_type": ["Debug"],
"arch": ["amd64"],
"suffix": "unity",
"extra_cmake_args": "-Dunity=ON"
"extra_cmake_args": "-Dunity=ON",
"exclude_event_types": ["pull_request"]
}
],
@@ -67,7 +68,7 @@
"compiler": ["gcc"],
"build_type": ["Release"],
"arch": ["amd64"],
"image": "ghcr.io/xrplf/xrpld/packaging-debian:sha-63ffdc3"
"image": "ghcr.io/xrplf/xrpld/packaging-debian:sha-577d745"
}
],
@@ -76,7 +77,7 @@
"compiler": ["gcc"],
"build_type": ["Release"],
"arch": ["amd64"],
"image": "ghcr.io/xrplf/xrpld/packaging-rhel:sha-63ffdc3"
"image": "ghcr.io/xrplf/xrpld/packaging-rhel:sha-577d745"
}
]
}

View File

@@ -9,7 +9,8 @@
{
"build_type": "Debug",
"extra_cmake_args": "-DCMAKE_POLICY_VERSION_MINIMUM=3.5",
"build_only": true
"build_only": true,
"exclude_event_types": ["pull_request"]
}
]
}

View File

@@ -1,8 +1,12 @@
{
"platform": "windows/amd64",
"runner": ["self-hosted", "Windows", "devbox"],
"runner": ["self-hosted", "Windows", "dev-box-windows-2026"],
"configs": [
{ "build_type": "Release" },
{ "build_type": "Debug", "build_only": true }
{
"build_type": "Debug",
"build_only": true,
"exclude_event_types": ["pull_request"]
}
]
}

View File

@@ -6,19 +6,23 @@ on:
- develop
paths:
- ".github/workflows/build-nix-images.yml"
- ".github/workflows/reusable-build-docker-image.yml"
- ".github/workflows/reusable-build-merge-docker-images.yml"
- "flake.nix"
- "flake.lock"
- "nix/**"
- "!nix/docker/README.md"
- "!nix/devshell.nix"
- "bin/check-tools.sh"
- "bin/install-sanitizer-libs.sh"
pull_request:
paths:
- ".github/workflows/build-nix-images.yml"
- ".github/workflows/reusable-build-docker-image.yml"
- ".github/workflows/reusable-build-merge-docker-images.yml"
- "flake.nix"
- "flake.lock"
- "nix/**"
- "!nix/docker/README.md"
- "!nix/devshell.nix"
- "bin/check-tools.sh"
- "bin/install-sanitizer-libs.sh"
workflow_dispatch:
concurrency:
@@ -50,8 +54,9 @@ jobs:
base_image: debian:bookworm
- name: rhel
base_image: registry.access.redhat.com/ubi9/ubi:latest
uses: ./.github/workflows/reusable-build-merge-docker-images.yml
uses: XRPLF/actions/.github/workflows/build-multiarch-image.yml@c1b480188519e0cad040e6aa70db1cbc5a797e07
with:
image_name: ghcr.io/xrplf/xrpld/nix-${{ matrix.distro.name }}
dockerfile: nix/docker/Dockerfile
base_image: ${{ matrix.distro.base_image }}
push: ${{ github.repository == 'XRPLF/rippled' && github.event_name == 'push' }}

View File

@@ -6,15 +6,11 @@ on:
- develop
paths:
- ".github/workflows/build-packaging-images.yml"
- ".github/workflows/reusable-build-docker-image.yml"
- ".github/workflows/reusable-build-merge-docker-images.yml"
- "package/Dockerfile"
- "package/install-packaging-tools.sh"
pull_request:
paths:
- ".github/workflows/build-packaging-images.yml"
- ".github/workflows/reusable-build-docker-image.yml"
- ".github/workflows/reusable-build-merge-docker-images.yml"
- "package/Dockerfile"
- "package/install-packaging-tools.sh"
workflow_dispatch:
@@ -42,8 +38,9 @@ jobs:
base_image: debian:bookworm
- name: rhel
base_image: registry.access.redhat.com/ubi9/ubi:latest
uses: ./.github/workflows/reusable-build-merge-docker-images.yml
uses: XRPLF/actions/.github/workflows/build-multiarch-image.yml@c1b480188519e0cad040e6aa70db1cbc5a797e07
with:
image_name: ghcr.io/xrplf/xrpld/packaging-${{ matrix.distro.name }}
dockerfile: package/Dockerfile
base_image: ${{ matrix.distro.base_image }}
push: ${{ github.repository == 'XRPLF/rippled' && github.event_name == 'push' }}

View File

@@ -41,7 +41,7 @@ env:
jobs:
build:
runs-on: ubuntu-latest
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-63ffdc3
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-fe4c8ae
steps:
- name: Checkout repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3

View File

@@ -1,89 +0,0 @@
# Build a single-platform Docker image. On push, the image is pushed to
# GHCR with arch-suffixed tags (e.g. `:latest-amd64`, `:sha-abc-amd64`)
# so the calling workflow can stitch per-arch builds into a multi-arch
# manifest without needing to pass digests around.
name: Reusable build Docker image (single platform)
on:
workflow_call:
inputs:
image_name:
description: "Full image name without tag (e.g. 'ghcr.io/xrplf/xrpld/nix-ubuntu')"
required: true
type: string
dockerfile:
description: "Path to the Dockerfile, relative to the repository root"
required: true
type: string
base_image:
description: "Value passed to the Dockerfile as the BASE_IMAGE build arg"
required: true
type: string
platform:
description: "Docker platform string, e.g. linux/amd64"
required: true
type: string
runner:
description: "GitHub Actions runner label to build on"
required: true
type: string
push:
description: "Whether to push the image to GHCR"
required: true
type: boolean
defaults:
run:
shell: bash
jobs:
build:
name: Build ${{ inputs.platform }}
runs-on: ${{ inputs.runner }}
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Determine arch
id: vars
env:
PLATFORM: ${{ inputs.platform }}
run: |
echo "arch=${PLATFORM##*/}" >>$GITHUB_OUTPUT
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
- name: Login to GitHub Container Registry
if: inputs.push
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Docker metadata
id: meta
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0
with:
images: ${{ inputs.image_name }}
tags: |
type=sha,prefix=sha-,format=short
type=raw,value=latest
flavor: |
suffix=-${{ steps.vars.outputs.arch }},onlatest=true
- name: Build and push
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
with:
context: .
file: ${{ inputs.dockerfile }}
platforms: ${{ inputs.platform }}
push: ${{ inputs.push }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: BASE_IMAGE=${{ inputs.base_image }}

View File

@@ -1,89 +0,0 @@
name: Reusable build and merge Docker image (multi-arch)
on:
workflow_call:
inputs:
image_name:
description: "Full image name without tag (e.g. 'ghcr.io/xrplf/xrpld/nix-ubuntu')"
required: true
type: string
dockerfile:
description: "Path to the Dockerfile, relative to the repository root"
required: true
type: string
base_image:
description: "Value passed to the Dockerfile as the BASE_IMAGE build arg"
required: true
type: string
defaults:
run:
shell: bash
jobs:
build:
name: Build ${{ inputs.image_name }}
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
target:
- platform: linux/amd64
runner: ubuntu-latest
- platform: linux/arm64
runner: ubuntu-24.04-arm
uses: ./.github/workflows/reusable-build-docker-image.yml
with:
image_name: ${{ inputs.image_name }}
dockerfile: ${{ inputs.dockerfile }}
base_image: ${{ inputs.base_image }}
platform: ${{ matrix.target.platform }}
runner: ${{ matrix.target.runner }}
push: ${{ github.repository == 'XRPLF/rippled' && github.event_name == 'push' }}
merge:
name: Merge ${{ inputs.image_name }}
needs: build
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
- name: Docker metadata
id: meta
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0
with:
images: ${{ inputs.image_name }}
tags: |
type=sha,prefix=sha-,format=short
type=raw,value=latest
- name: Login to GitHub Container Registry
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create multi-arch manifests
if: ${{ github.repository == 'XRPLF/rippled' && github.event_name == 'push' }}
run: |
for tag in $(jq -cr '.tags[]' <<<"$DOCKER_METADATA_OUTPUT_JSON"); do
docker buildx imagetools create -t "$tag" "${tag}-amd64" "${tag}-arm64"
done
- name: Inspect image
if: ${{ github.repository == 'XRPLF/rippled' && github.event_name == 'push' }}
env:
IMAGE_NAME: ${{ inputs.image_name }}
IMAGE_VERSION: ${{ steps.meta.outputs.version }}
run: |
docker buildx imagetools inspect "${IMAGE_NAME}:${IMAGE_VERSION}"

View File

@@ -82,7 +82,7 @@ jobs:
name: ${{ inputs.config_name }}
runs-on: ${{ fromJSON(inputs.runs_on) }}
container: ${{ inputs.image != '' && inputs.image || null }}
timeout-minutes: ${{ inputs.sanitizers != '' && 360 || 60 }}
timeout-minutes: ${{ inputs.sanitizers != '' && 360 || 90 }}
env:
# Use a namespace to keep the objects separate for each configuration.
CCACHE_NAMESPACE: ${{ inputs.config_name }}
@@ -121,6 +121,11 @@ jobs:
if: ${{ inputs.ccache_enabled && runner.debug == '1' }}
run: echo "CCACHE_LOGFILE=${{ runner.temp }}/ccache.log" >>"${GITHUB_ENV}"
- name: Check tools
env:
CHECK_TOOLS_SKIP_CLONE: "1"
run: ./bin/check-tools.sh
- name: Print build environment
uses: XRPLF/actions/print-build-env@59dec886e4afb05a1724443af08baccbc045b574
@@ -164,6 +169,27 @@ jobs:
${CMAKE_ARGS} \
..
# Export the sanitizer options before any instrumented binary runs. The
# protocol code-gen and build steps below invoke instrumented dependency
# tools (protoc, grpc), so setting UBSAN_OPTIONS here lets the UBSan
# suppression list silence their diagnostics too, not just at test time.
# GITHUB_WORKSPACE (not the github.workspace context) is used so the path
# resolves correctly inside the container job.
- name: Set sanitizer options
if: ${{ !inputs.build_only && env.SANITIZERS_ENABLED == 'true' }}
env:
CONFIG_NAME: ${{ inputs.config_name }}
run: |
SUPP="${GITHUB_WORKSPACE}/sanitizers/suppressions"
ASAN_OPTS="include=${SUPP}/runtime-asan-options.txt:suppressions=${SUPP}/asan.supp"
if [[ "${CONFIG_NAME}" == *gcc* ]]; then
ASAN_OPTS="${ASAN_OPTS}:alloc_dealloc_mismatch=0"
fi
echo "ASAN_OPTIONS=${ASAN_OPTS}" >>${GITHUB_ENV}
echo "TSAN_OPTIONS=include=${SUPP}/runtime-tsan-options.txt:suppressions=${SUPP}/tsan.supp" >>${GITHUB_ENV}
echo "UBSAN_OPTIONS=include=${SUPP}/runtime-ubsan-options.txt:suppressions=${SUPP}/ubsan.supp" >>${GITHUB_ENV}
echo "LSAN_OPTIONS=include=${SUPP}/runtime-lsan-options.txt:suppressions=${SUPP}/lsan.supp" >>${GITHUB_ENV}
- name: Check protocol autogen files are up-to-date
working-directory: ${{ env.BUILD_DIR }}
env:
@@ -279,20 +305,6 @@ jobs:
run: |
./xrpld --version | grep libvoidstar
- name: Set sanitizer options
if: ${{ !inputs.build_only && env.SANITIZERS_ENABLED == 'true' }}
env:
CONFIG_NAME: ${{ inputs.config_name }}
run: |
ASAN_OPTS="include=${GITHUB_WORKSPACE}/sanitizers/suppressions/runtime-asan-options.txt:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/asan.supp"
if [[ "${CONFIG_NAME}" == *gcc* ]]; then
ASAN_OPTS="${ASAN_OPTS}:alloc_dealloc_mismatch=0"
fi
echo "ASAN_OPTIONS=${ASAN_OPTS}" >>${GITHUB_ENV}
echo "TSAN_OPTIONS=include=${GITHUB_WORKSPACE}/sanitizers/suppressions/runtime-tsan-options.txt:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/tsan.supp" >>${GITHUB_ENV}
echo "UBSAN_OPTIONS=include=${GITHUB_WORKSPACE}/sanitizers/suppressions/runtime-ubsan-options.txt:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/ubsan.supp" >>${GITHUB_ENV}
echo "LSAN_OPTIONS=include=${GITHUB_WORKSPACE}/sanitizers/suppressions/runtime-lsan-options.txt:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/lsan.supp" >>${GITHUB_ENV}
- name: Run the separate tests
if: ${{ !inputs.build_only }}
working-directory: ${{ runner.os == 'Windows' && format('{0}/{1}', env.BUILD_DIR, inputs.build_type) || env.BUILD_DIR }}

View File

@@ -36,7 +36,7 @@ jobs:
needs: [determine-files]
if: ${{ always() && !cancelled() && (!inputs.check_only_changed || needs.determine-files.outputs.cpp_changed_files != '' || needs.determine-files.outputs.clang_tidy_config_changed == 'true') }}
runs-on: ["self-hosted", "Linux", "X64", "heavy"]
container: "ghcr.io/xrplf/xrpld/nix-debian:sha-63ffdc3"
container: "ghcr.io/xrplf/xrpld/nix-debian:sha-fe4c8ae"
permissions:
contents: read
issues: write

View File

@@ -35,4 +35,5 @@ jobs:
id: generate
env:
GENERATE_CONFIG: ${{ inputs.os != '' && format('--config={0}', inputs.os) || '' }}
run: ./generate.py ${GENERATE_CONFIG} >>"${GITHUB_OUTPUT}"
GENERATE_EVENT: ${{ github.event_name }}
run: ./generate.py ${GENERATE_CONFIG} --event="${GENERATE_EVENT}" >>"${GITHUB_OUTPUT}"

View File

@@ -40,7 +40,7 @@ defaults:
jobs:
upload:
runs-on: ubuntu-latest
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-63ffdc3
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-fe4c8ae
steps:
- name: Checkout repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3

View File

@@ -30,6 +30,7 @@ on:
- ".github/scripts/strategy-matrix/**"
- conanfile.py
- conan.lock
- conan/profiles/**
env:
CONAN_REMOTE_NAME: xrplf

391
BUILD.md
View File

@@ -1,26 +1,57 @@
| :warning: **WARNING** :warning: |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| These instructions assume you have a C++ development environment ready with Git, Python, Conan, CMake, and a C++ compiler. For help setting one up on Linux, macOS, or Windows, [see this guide](./docs/build/environment.md). |
| :warning: **WARNING** :warning: |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| These instructions assume you have a C++ development environment ready with Git, Python, Conan, CMake, and a C++ compiler. For help setting one up on Linux, macOS, or Windows, [see this guide](./docs/build/environment.md).<br><br>These instructions also assume a basic familiarity with Conan and CMake. If you are unfamiliar with Conan, you can read our [crash course](./docs/build/conan.md) or the official [Getting Started][conan-getting-started] walkthrough. |
> These instructions also assume a basic familiarity with Conan and CMake.
> If you are unfamiliar with Conan, you can read our
> [crash course](./docs/build/conan.md) or the official [Getting Started][3]
> walkthrough.
## Minimum Requirements
## Branches
See [System Requirements](https://xrpl.org/system-requirements.html).
For a stable release, choose the `master` branch or one of the [tagged
releases](https://github.com/XRPLF/rippled/releases).
Building xrpld generally requires Git, Python, Conan, CMake, and a C++
compiler.
- [Python](https://www.python.org/downloads/)
- [Conan](https://conan.io/downloads.html)
- [CMake](https://cmake.org/download/)
You can verify that the required tools are installed and runnable with:
```bash
git checkout master
./bin/check-tools.sh
```
For the latest release candidate, choose the `release` branch.
`xrpld` is written in the C++23 dialect. The [tested compiler versions][cpp23-support] are:
```bash
git checkout release
```
| Compiler | Version |
| ----------- | --------------- |
| GCC | 15.2 |
| Clang | 22 |
| Apple Clang | 17 |
| MSVC | 19.44[^windows] |
## Operating Systems
Please see the [environment setup guide](./docs/build/environment.md) for detailed instructions for all platforms.
### Linux
The Ubuntu Linux distribution has received the highest level of quality
assurance, testing, and support. We also support Red Hat and use Debian
internally.
Our Linux CI tooling is distro-independent and uses a Nix-based environment, so it should be possible to build on other Linux distributions as well, although we have not tested them.
### macOS
Many `xrpld` engineers use macOS for development.
### Windows
Windows is used by some engineers for development only.
[^windows]: Windows is not recommended for production use.
## Steps
### Branches
For the latest set of untested features, or to contribute, choose the `develop`
branch.
@@ -29,55 +60,15 @@ branch.
git checkout develop
```
## Minimum Requirements
For a release candidate, choose the relevant release branch, e.g.
`release/3.2.x`.
See [System Requirements](https://xrpl.org/system-requirements.html).
```bash
git checkout release/3.2.x
```
Building xrpld generally requires git, Python, Conan, CMake, and a C++
compiler. Some guidance on setting up such a [C++ development environment can be
found here](./docs/build/environment.md).
- [Python 3.11](https://www.python.org/downloads/), or higher
- [Conan 2.17](https://conan.io/downloads.html)[^1], or higher
- [CMake 3.22](https://cmake.org/download/), or higher
[^1]:
It is possible to build with Conan 1.60+, but the instructions are
significantly different, which is why we are not recommending it.
`xrpld` is written in the C++20 dialect and includes the `<concepts>` header.
The [minimum compiler versions][2] required are:
| Compiler | Version |
| ----------- | --------- |
| GCC | 12 |
| Clang | 16 |
| Apple Clang | 16 |
| MSVC | 19.44[^3] |
### Linux
The Ubuntu Linux distribution has received the highest level of quality
assurance, testing, and support. We also support Red Hat and use Debian
internally.
Here are [sample instructions for setting up a C++ development environment on
Linux](./docs/build/environment.md#linux).
### Mac
Many xrpld engineers use macOS for development.
Here are [sample instructions for setting up a C++ development environment on
macOS](./docs/build/environment.md#macos).
### Windows
Windows is used by some engineers for development only.
[^3]: Windows is not recommended for production use.
## Steps
For a stable release, choose one of the [tagged
releases](https://github.com/XRPLF/rippled/releases).
### Set Up Conan
@@ -86,18 +77,11 @@ Conan, CMake, and a C++ compiler, you may need to set up your Conan profile.
These instructions assume a basic familiarity with Conan and CMake. If you are
unfamiliar with Conan, then please read [this crash course](./docs/build/conan.md) or the official
[Getting Started][3] walkthrough.
[Getting Started][conan-getting-started] walkthrough.
#### Conan lockfile
#### Profiles
To achieve reproducible dependencies, we use a [Conan lockfile](https://docs.conan.io/2/tutorial/versioning/lockfiles.html),
which has to be updated every time dependencies change.
Please see the [instructions on how to regenerate the lockfile](conan/lockfile/README.md).
#### Default profile
We recommend that you import the provided `conan/profiles/default` profile:
We recommend that you install our Conan profiles:
```bash
conan config install conan/profiles/ -tf $(conan config home)/profiles/
@@ -109,222 +93,15 @@ You can check your Conan profile by running:
conan profile show
```
#### Custom profile
If the default profile is not suitable for your environment, you can create a custom profile and pass it to Conan.
More information on customizing Conan can be found in the [Advanced Conan configuration](./docs/build/advanced_conan.md).
If the default profile does not work for you and you do not yet have a Conan
profile, you can create one by running:
#### Add xrplf remote
Run the following command to add the `xrplf` remote, which hosts some of our dependencies:
```bash
conan profile detect
```
You may need to make changes to the profile to suit your environment. You can
refer to the provided `conan/profiles/default` profile for inspiration, and you
may also need to apply the required [tweaks](#conan-profile-tweaks) to this
default profile.
### Patched recipes
Occasionally, we need patched recipes or recipes not present in Conan Center.
We maintain a fork of the Conan Center Index
[here](https://github.com/XRPLF/conan-center-index/) containing the modified and newly added recipes.
To ensure our patched recipes are used, you must add our Conan remote at a
higher index than the default Conan Center remote, so it is consulted first. You
can do this by running:
```bash
conan remote add --index 0 xrplf https://conan.ripplex.io
```
Alternatively, you can pull our recipes from the repository and export them locally:
```bash
# Define which recipes to export.
recipes=('abseil' 'ed25519' 'mpt-crypto' 'openssl' 'secp256k1' 'snappy' 'soci' 'wasm-xrplf' 'wasmi')
# Selectively check out the recipes from our CCI fork.
cd external
mkdir -p conan-center-index
cd conan-center-index
git init
git remote add origin git@github.com:XRPLF/conan-center-index.git
git sparse-checkout init
for recipe in "${recipes[@]}"; do
echo "Checking out recipe '${recipe}'..."
git sparse-checkout add recipes/${recipe}
done
git fetch origin master
git checkout master
./export_all.sh
cd ../../
```
In the case we switch to a newer version of a dependency that still requires a
patch or add a new dependency, it will be necessary for you to pull in the changes and re-export the
updated dependencies with the newer version. However, if we switch to a newer
version that no longer requires a patch, no action is required on your part, as
the new recipe will be automatically pulled from the official Conan Center.
> [!NOTE]
> You might need to add `--lockfile=""` to your `conan install` command
> to avoid automatic use of the existing `conan.lock` file when you run
> `conan export` manually on your machine
>
> This is not recommended though, as you might end up using different revisions of recipes.
### Conan profile tweaks
#### Missing compiler version
If you see an error similar to the following after running `conan profile show`:
```text
ERROR: Invalid setting '17' is not a valid 'settings.compiler.version' value.
Possible values are ['5.0', '5.1', '6.0', '6.1', '7.0', '7.3', '8.0', '8.1',
'9.0', '9.1', '10.0', '11.0', '12.0', '13', '13.0', '13.1', '14', '14.0', '15',
'15.0', '16', '16.0']
Read "http://docs.conan.io/2/knowledge/faq.html#error-invalid-setting"
```
you need to add your compiler to the list of compiler versions in
`$(conan config home)/settings_user.yml`, by adding the required version number(s)
to the `version` array specific for your compiler. For example:
```yaml
compiler:
apple-clang:
version: ["17.0"]
```
#### Multiple compilers
If you have multiple compilers installed, make sure to select the one to use in
your default Conan configuration **before** running `conan profile detect`, by
setting the `CC` and `CXX` environment variables.
For example, if you are running MacOS and have [homebrew
LLVM@18](https://formulae.brew.sh/formula/llvm@18), and want to use it as a
compiler in the new Conan profile:
```bash
export CC=$(brew --prefix llvm@18)/bin/clang
export CXX=$(brew --prefix llvm@18)/bin/clang++
conan profile detect
```
You should also explicitly set the path to the compiler in the profile file,
which helps to avoid errors when `CC` and/or `CXX` are set and disagree with the
selected Conan profile. For example:
```text
[conf]
tools.build:compiler_executables={'c':'/usr/bin/gcc','cpp':'/usr/bin/g++'}
```
#### Multiple profiles
You can manage multiple Conan profiles in the directory
`$(conan config home)/profiles`, for example renaming `default` to a different
name and then creating a new `default` profile for a different compiler.
#### Select language
The default profile created by Conan will typically select different C++ dialect
than C++20 used by this project. You should set `20` in the profile line
starting with `compiler.cppstd=`. For example:
```bash
sed -i.bak -e 's|^compiler\.cppstd=.*$|compiler.cppstd=20|' $(conan config home)/profiles/default
```
#### Select standard library in Linux
**Linux** developers will commonly have a default Conan [profile][] that
compiles with GCC and links with libstdc++. If you are linking with libstdc++
(see profile setting `compiler.libcxx`), then you will need to choose the
`libstdc++11` ABI:
```bash
sed -i.bak -e 's|^compiler\.libcxx=.*$|compiler.libcxx=libstdc++11|' $(conan config home)/profiles/default
```
#### Select architecture and runtime in Windows
**Windows** developers may need to use the x64 native build tools. An easy way
to do that is to run the shortcut "x64 Native Tools Command Prompt" for the
version of Visual Studio that you have installed.
Windows developers must also build `xrpld` and its dependencies for the x64
architecture:
```bash
sed -i.bak -e 's|^arch=.*$|arch=x86_64|' $(conan config home)/profiles/default
```
**Windows** developers also must select static runtime:
```bash
sed -i.bak -e 's|^compiler\.runtime=.*$|compiler.runtime=static|' $(conan config home)/profiles/default
```
#### Clang workaround for grpc
If your compiler is clang, version 19 or later, or apple-clang, version 17 or
later, you may encounter a compilation error while building the `grpc`
dependency:
```text
In file included from .../lib/promise/try_seq.h:26:
.../lib/promise/detail/basic_seq.h:499:38: error: a template argument list is expected after a name prefixed by the template keyword [-Wmissing-template-arg-list-after-template-kw]
499 | Traits::template CallSeqFactory(f_, *cur_, std::move(arg)));
| ^
```
The workaround for this error is to add two lines to profile:
```text
[conf]
tools.build:cxxflags=['-Wno-missing-template-arg-list-after-template-kw']
```
#### Workaround for gcc 12
If your compiler is gcc, version 12, and you have enabled `werr` option, you may
encounter a compilation error such as:
```text
/usr/include/c++/12/bits/char_traits.h:435:56: error: 'void* __builtin_memcpy(void*, const void*, long unsigned int)' accessing 9223372036854775810 or more bytes at offsets [2, 9223372036854775807] and 1 may overlap up to 9223372036854775813 bytes at offset -3 [-Werror=restrict]
435 | return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n));
| ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~
cc1plus: all warnings being treated as errors
```
The workaround for this error is to add two lines to your profile:
```text
[conf]
tools.build:cxxflags=['-Wno-restrict']
```
#### Workaround for clang 16
If your compiler is clang, version 16, you may encounter compilation error such
as:
```text
In file included from .../boost/beast/websocket/stream.hpp:2857:
.../boost/beast/websocket/impl/read.hpp:695:17: error: call to 'async_teardown' is ambiguous
async_teardown(impl.role, impl.stream(),
^~~~~~~~~~~~~~
```
The workaround for this error is to add two lines to your profile:
```text
[conf]
tools.build:cxxflags=['-DBOOST_ASIO_DISABLE_CONCEPTS']
conan remote add --index 0 --force xrplf https://conan.ripplex.io
```
### Set Up Ccache
@@ -333,14 +110,7 @@ To speed up repeated compilations, we recommend that you install
[ccache](https://ccache.dev), a tool that wraps your compiler so that it can
cache build objects locally.
#### Linux
You can install it using the package manager, e.g. `sudo apt install ccache`
(Ubuntu) or `sudo dnf install ccache` (RHEL).
#### macOS
You can install it using Homebrew, i.e. `brew install ccache`.
On Linux and macOS, `ccache` is included in the [Nix development shell](./docs/build/nix.md).
#### Windows
@@ -549,7 +319,7 @@ See [Sanitizers docs](./docs/build/sanitizers.md) for more details.
| Option | Default Value | Description |
| ---------- | ------------- | -------------------------------------------------------------- |
| `assert` | OFF | Enable assertions. |
| `assert` | OFF | Force enabling assertions. |
| `coverage` | OFF | Prepare the coverage report. |
| `tests` | OFF | Build tests. |
| `unity` | OFF | Configure a unity build. |
@@ -557,7 +327,7 @@ See [Sanitizers docs](./docs/build/sanitizers.md) for more details.
| `werr` | OFF | Treat compilation warnings as errors |
| `wextra` | OFF | Enable additional compilation warnings |
[Unity builds][5] may be faster for the first build (at the cost of much more
[Unity builds][unity-build] may be faster for the first build (at the cost of much more
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.
@@ -583,14 +353,14 @@ After any updates or changes to dependencies, you may need to do the following:
conan remove '*'
```
3. Re-run [conan export](#patched-recipes) if needed.
4. [Regenerate lockfile](#conan-lockfile).
3. Re-run [conan export](./docs/build/advanced_conan.md#patched-recipes) if needed.
4. [Regenerate lockfile](./docs/build/advanced_conan.md#conan-lockfile).
5. Re-run [conan install](#build-and-test).
#### ERROR: Package not resolved
If you're seeing an error like `ERROR: Package 'snappy/1.1.10' not resolved: Unable to find 'snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1756234314.246' in remotes.`,
please add `xrplf` remote or re-run `conan export` for [patched recipes](#patched-recipes).
please [add `xrplf` remote](#add-xrplf-remote) or re-run `conan export` for [patched recipes](./docs/build/advanced_conan.md#patched-recipes).
### `protobuf/port_def.inc` file not found
@@ -610,28 +380,9 @@ For example, if you want to build Debug:
1. For conan install, pass `--settings build_type=Debug`
2. For cmake, pass `-DCMAKE_BUILD_TYPE=Debug`
## Add a Dependency
If you want to experiment with a new package, follow these steps:
1. Search for the package on [Conan Center](https://conan.io/center/).
2. Modify [`conanfile.py`](./conanfile.py):
- Add a version of the package to the `requires` property.
- Change any default options for the package by adding them to the
`default_options` property (with syntax `'$package:$option': $value`).
3. Modify [`CMakeLists.txt`](./CMakeLists.txt):
- Add a call to `find_package($package REQUIRED)`.
- Link a library from the package to the target `xrpl_libs`
(search for the existing call to `target_link_libraries(xrpl_libs INTERFACE ...)`).
4. Start coding! Don't forget to include whatever headers you need from the package.
[1]: https://github.com/conan-io/conan-center-index/issues/13168
[2]: https://en.cppreference.com/w/cpp/compiler_support/20
[3]: https://docs.conan.io/en/latest/getting_started.html
[5]: https://en.wikipedia.org/wiki/Unity_build
[6]: https://github.com/boostorg/beast/issues/2648
[7]: https://github.com/boostorg/beast/issues/2661
[cpp23-support]: https://en.cppreference.com/w/cpp/compiler_support/23
[conan-getting-started]: https://docs.conan.io/en/latest/getting_started.html
[unity-build]: https://en.wikipedia.org/wiki/Unity_build
[gcovr]: https://gcovr.com/en/stable/getting-started.html
[python-pip]: https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/
[build_type]: https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html
[profile]: https://docs.conan.io/en/latest/reference/profiles.html

View File

@@ -15,7 +15,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
project(xrpl)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

View File

@@ -14,9 +14,9 @@ The following branches exist in the main project repository:
- `develop`: The latest set of unreleased features, and the most common
starting point for contributions.
- `release`: The latest beta release or release candidate.
- `master`: The latest stable release.
- `gh-pages`: The documentation for this project, built by Doxygen.
- `release/*` (e.g. `release/3.2.x`): Release branches, one per release line,
holding the latest release candidate, or stable release for that line.
Stable releases are published as [tagged releases](https://github.com/XRPLF/rippled/releases).
The tip of each branch must be signed. In order for GitHub to sign a
squashed commit that it builds from your pull request, GitHub must know
@@ -130,11 +130,9 @@ tl;dr
## Pull requests
In general, pull requests use `develop` as the base branch.
The exceptions are
- Fixes and improvements to a release candidate use `release` as the
base.
- Hotfixes use `master` as the base.
The exceptions are fixes, improvements, and hotfixes for an existing release,
which use that release's branch (e.g. `release/3.2.x`) as the base.
If your changes are not quite ready, but you want to make it easily available
for preliminary examination or review, you can create a "Draft" pull request.
@@ -216,7 +214,7 @@ coherent rather than a set of _thou shalt not_ commandments.
## Formatting
All code must conform to `clang-format` version 21,
All code must conform to `clang-format` version 22,
according to the settings in [`.clang-format`](./.clang-format),
unless the result would be unreasonably difficult to read or maintain.
To demarcate lines that should be left as-is, surround them with comments like
@@ -261,7 +259,7 @@ This ensures that configuration changes don't introduce new warnings across the
### Installing clang-tidy
See the [environment setup guide](./docs/build/environment.md#clang-tidy) for platform-specific installation instructions.
See the [environment setup guide](./docs/build/environment.md#clang-tidy) for how to get clang-tidy.
### Running clang-tidy locally

158
bin/check-tools.sh Executable file
View File

@@ -0,0 +1,158 @@
#!/usr/bin/env bash
#
# check-tools.sh — verify the xrpld development tooling is present and runnable.
#
# Works on Linux, macOS, and Windows (Git Bash / MSYS). For every expected tool
# it runs a version probe, collecting anything that is missing or fails to run,
# and prints a summary at the end (exiting non-zero if anything is missing).
#
# The tool set is platform-aware:
# - Linux: the full Nix CI environment (see nix/packages.nix, nix/ci-env.nix),
# with GCC, Clang and the sanitizer/coverage tooling. This script is
# run during the Nix Docker image build (nix/docker/Dockerfile), so
# the Linux list is kept in sync with that environment.
# - macOS: the same tooling, minus GCC/g++/gcov/mold
# - 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, 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.
# CHECK_TOOLS_SKIP_CLONE if set, skip the git-over-HTTPS connectivity check.
set -uo pipefail
missing=()
checked=0
# check <name> [probe-command...]
# Runs the probe (default: "<name> --version") quietly. Records <name> as
# missing if the command is not found or exits non-zero.
check() {
local name="$1"
shift
local -a probe=("$@")
if [ "${#probe[@]}" -eq 0 ]; then
probe=("${name}" --version)
fi
echo "Checking ${name}..."
checked=$((checked + 1))
if "${probe[@]}" | head -n 1; then
printf ' [ ok ] %s\n' "${name}"
else
printf ' [MISS] %s\n' "${name}"
missing+=("${name}")
fi
}
case "$(uname -s)" in
Linux*) os=linux ;;
Darwin*) os=macos ;;
MINGW* | MSYS* | CYGWIN*) os=windows ;;
*)
echo "Unknown OS: $(uname -s)" >&2
exit 1
;;
esac
echo "Detected OS: ${os} ($(uname -s) $(uname -m))"
echo
echo "Core build tools:"
check cmake
check conan
check git
if [ "${os}" = "windows" ]; then
check python python --version
else
check python3
fi
# The full development toolchain. Available from Nix on Linux and macOS; on
# Windows these are typically not installed, so they are skipped.
if [ "${os}" = "linux" ] || [ "${os}" = "macos" ]; then
echo
echo "Development tooling:"
check ccache
check clang
check clang++
check ClangBuildAnalyzer
check curl
check file
check less
check make
check netstat which netstat
check ninja
check perl
check pkg-config
check vim
# These tools are present in our Linux CI images and in local development
# 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-format
check doxygen
check gcovr
check gh
check git-cliff
check gpg
# 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
fi
fi
# GCC is the default compiler on Linux. macOS uses the system Apple Clang
# instead, so GCC/g++/gcov are not expected there.
if [ "${os}" = "linux" ]; then
echo
echo "GCC toolchain:"
check gcc
check g++
check gcov
echo
echo "Mold:"
check mold
fi
if [ "${os}" = "windows" ]; then
echo
echo "Note: on Windows the C++ compiler is MSVC, which is provided"
echo " separately (e.g. via Visual Studio) and is not checked here."
fi
# A simple test to verify that git can clone a repository over HTTPS
# (i.e. the CA bundle is wired up). Clone to a temp dir and clean up.
if [ -n "${CHECK_TOOLS_SKIP_CLONE:-}" ]; then
echo
echo "Skipping git-over-HTTPS check (CHECK_TOOLS_SKIP_CLONE is set)."
else
echo
echo "Connectivity check:"
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 ' [ ok ] git clone over HTTPS\n'
else
printf ' [MISS] git clone over HTTPS\n'
missing+=("git-https-clone")
fi
rm -rf "${tmp_clone}"
fi
echo
if [ "${#missing[@]}" -eq 0 ]; then
echo "All ${checked} checked tools are present and runnable."
else
echo "Missing or non-functional tools (${#missing[@]} of ${checked}):" >&2
for tool in "${missing[@]}"; do
echo " - ${tool}" >&2
done
exit 1
fi

View File

@@ -94,6 +94,9 @@ add_module(xrpl basics)
target_link_libraries(xrpl.libxrpl.basics PUBLIC xrpl.libxrpl.beast)
# Level 03
add_module(xrpl config)
target_link_libraries(xrpl.libxrpl.config PUBLIC xrpl.libxrpl.basics)
add_module(xrpl json)
target_link_libraries(xrpl.libxrpl.json PUBLIC xrpl.libxrpl.basics)
@@ -120,6 +123,7 @@ target_link_libraries(
xrpl.libxrpl.core
PUBLIC
xrpl.libxrpl.basics
xrpl.libxrpl.config
xrpl.libxrpl.json
xrpl.libxrpl.protocol
xrpl.libxrpl.protocol_autogen
@@ -143,7 +147,11 @@ target_link_libraries(
add_module(xrpl nodestore)
target_link_libraries(
xrpl.libxrpl.nodestore
PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.json xrpl.libxrpl.protocol
PUBLIC
xrpl.libxrpl.basics
xrpl.libxrpl.config
xrpl.libxrpl.json
xrpl.libxrpl.protocol
)
add_module(xrpl shamap)
@@ -159,13 +167,14 @@ target_link_libraries(
add_module(xrpl rdb)
target_link_libraries(
xrpl.libxrpl.rdb
PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.core
PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.config xrpl.libxrpl.core
)
add_module(xrpl server)
target_link_libraries(
xrpl.libxrpl.server
PUBLIC
xrpl.libxrpl.config
xrpl.libxrpl.protocol
xrpl.libxrpl.core
xrpl.libxrpl.rdb
@@ -210,6 +219,7 @@ target_link_modules(
basics
beast
conditions
config
core
crypto
git

View File

@@ -1,9 +1,9 @@
{
"version": "0.5",
"requires": [
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1777558780.503",
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1778091116.056",
"xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1765850149.987",
"sqlite3/3.53.0#324ada52333108388a9a6108bfa96734%1776096494.149",
"sqlite3/3.53.0#324ada52333108388a9a6108bfa96734%1778091117.311",
"soci/4.0.3#fe32b9ad5eb47e79ab9e45a68f363945%1774450067.231",
"snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1765850147.878",
"secp256k1/0.7.1#481881709eb0bdd0185a12b912bbe8ad%1770910500.329",
@@ -15,19 +15,19 @@
"lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1765850143.914",
"libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1765842973.492",
"libbacktrace/cci.20210118#a7691bfccd8caaf66309df196790a5a1%1765842973.03",
"libarchive/3.8.7#c446109bd1f1d8ba7936c94189bc50e6%1776147552.838",
"libarchive/3.8.7#c446109bd1f1d8ba7936c94189bc50e6%1778091117.848",
"jemalloc/5.3.1#1fc58d55316041f10fbc1e8a2eae632a%1776700028.228",
"gtest/1.17.0#5224b3b3ff3b4ce1133cbdd27d53ee7d%1768312129.152",
"grpc/1.78.1#b1a9e74b145cc471bed4dc64dc6eb2c1%1774467387.342",
"grpc/1.81.0#2fb144aeb47e7f35c6ebb0e5f35bed31%1781620605.685",
"ed25519/2015.03#ae761bdc52730a843f0809bdf6c1b1f6%1765850143.772",
"date/3.0.4#862e11e80030356b53c2c38599ceb32b%1765850143.772",
"c-ares/1.34.6#545240bb1c40e2cacd4362d6b8967650%1774439234.681",
"bzip2/1.0.8#c470882369c2d95c5c77e970c0c7e321%1765850143.837",
"boost/1.91.0#ea540ca2133d831b560036aa24dece3c%1778050991.9",
"boost/1.91.0#ea540ca2133d831b560036aa24dece3c%1778091165.282",
"abseil/20250127.0#bb0baf1f362bc4a725a24eddd419b8f7%1774365460.196"
],
"build_requires": [
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1777558780.503",
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1778091116.056",
"strawberryperl/5.32.1.1#8d114504d172cfea8ea1662d09b6333e%1774447376.964",
"protobuf/6.33.5#d96d52ba5baaaa532f47bda866ad87a5%1774467363.12",
"nasm/2.16.01#31e26f2ee3c4346ecd347911bd126904%1765850144.707",

View File

@@ -2,7 +2,7 @@
arch=x86_64
build_type=Release
compiler=gcc
compiler.cppstd=20
compiler.cppstd=23
compiler.libcxx=libstdc++11
compiler.version=13
os=Linux

View File

@@ -2,7 +2,7 @@
arch=armv8
build_type=Release
compiler=apple-clang
compiler.cppstd=20
compiler.cppstd=23
compiler.libcxx=libc++
compiler.version=17.0
os=Macos

View File

@@ -2,7 +2,7 @@
arch=x86_64
build_type=Release
compiler=msvc
compiler.cppstd=20
compiler.cppstd=23
compiler.runtime=dynamic
compiler.runtime_type=Release
compiler.version=194

View File

@@ -12,7 +12,7 @@ arch={{ arch }}
build_type=Debug
compiler={{compiler}}
compiler.version={{ compiler_version }}
compiler.cppstd=20
compiler.cppstd=23
{% if os == "Windows" %}
compiler.runtime=static
{% else %}

View File

@@ -52,52 +52,50 @@ include(default)
{% endif %}
{# Frame pointer required for meaningful stack traces; -O1 for reasonable performance #}
{% set compile_flags = ["-fno-omit-frame-pointer", "-O1"] %}
{% set sanitizer_compiler_flags = ["-fno-omit-frame-pointer", "-O1"] %}
{% if compiler == "gcc" %}
{# Suppress false positive warnings with GCC #}
{% set _ = compile_flags.append("-Wno-stringop-overflow") %}
{% set _ = sanitizer_compiler_flags.append("-Wno-stringop-overflow") %}
{% set relocation_flags = [] %}
{% if arch == "x86_64" and enable_asan %}
{# Large code model prevents relocation errors in instrumented ASAN binaries #}
{% set _ = compile_flags.append("-mcmodel=large") %}
{% set _ = sanitizer_compiler_flags.append("-mcmodel=large") %}
{% set _ = relocation_flags.append("-mcmodel=large") %}
{% elif enable_tsan %}
{# GCC doesn't support atomic_thread_fence with TSAN; suppress warnings #}
{% set _ = compile_flags.append("-Wno-tsan") %}
{% set _ = sanitizer_compiler_flags.append("-Wno-tsan") %}
{% if arch == "x86_64" %}
{# Medium code model for TSAN; large is incompatible #}
{% set _ = compile_flags.append("-mcmodel=medium") %}
{% set _ = sanitizer_compiler_flags.append("-mcmodel=medium") %}
{% set _ = relocation_flags.append("-mcmodel=medium") %}
{% endif %}
{% endif %}
{% set fsanitize = "-fsanitize=" ~ ",".join(sanitizer_types) %}
{% set _ = compile_flags.append(fsanitize) %}
{% set _ = sanitizer_compiler_flags.append(fsanitize) %}
{% set _ = relocation_flags.append(fsanitize) %}
{% set sanitizer_compiler_flags = " ".join(compile_flags) %}
{% set sanitizer_linker_flags = " ".join(relocation_flags) %}
{% set sanitizer_linker_flags = relocation_flags %}
{% elif compiler == "clang" or compiler == "apple-clang" %}
{% set fsanitize = "-fsanitize=" ~ ",".join(sanitizer_types) %}
{% set _ = compile_flags.append(fsanitize) %}
{% set _ = sanitizer_compiler_flags.append(fsanitize) %}
{% set sanitizer_compiler_flags = " ".join(compile_flags) %}
{% set sanitizer_linker_flags = fsanitize %}
{% set sanitizer_linker_flags = [fsanitize] %}
{% endif %}
[conf]
tools.build:defines+={{defines}}
tools.build:cxxflags+=['{{sanitizer_compiler_flags}}']
tools.build:sharedlinkflags+=['{{sanitizer_linker_flags}}']
tools.build:exelinkflags+=['{{sanitizer_linker_flags}}']
tools.build:cxxflags+={{sanitizer_compiler_flags}}
tools.build:sharedlinkflags+={{sanitizer_linker_flags}}
tools.build:exelinkflags+={{sanitizer_linker_flags}}
tools.info.package_id:confs+=["tools.build:cxxflags", "tools.build:exelinkflags", "tools.build:sharedlinkflags", "tools.build:defines"]
# &: means "apply only to the consumer/root package"
&:tools.cmake.cmaketoolchain:extra_variables={"SANITIZERS": "{{sanitizers}}", "SANITIZERS_COMPILER_FLAGS": "{{sanitizer_compiler_flags}}", "SANITIZERS_LINKER_FLAGS": "{{sanitizer_linker_flags}}"}
&:tools.cmake.cmaketoolchain:extra_variables={"SANITIZERS": "{{sanitizers}}", "SANITIZERS_COMPILER_FLAGS": "{{sanitizer_compiler_flags | join(' ')}}", "SANITIZERS_LINKER_FLAGS": "{{sanitizer_linker_flags | join(' ')}}"}
[options]
{% if enable_asan %}

View File

@@ -28,7 +28,7 @@ class Xrpl(ConanFile):
requires = [
"ed25519/2015.03",
"grpc/1.78.1",
"grpc/1.81.0",
"libarchive/3.8.7",
"nudb/2.0.9",
"openssl/3.6.2",

View File

@@ -84,6 +84,7 @@ words:
- coro
- coros
- cowid
- cpack
- cryptocondition
- cryptoconditional
- cryptoconditions
@@ -108,6 +109,7 @@ words:
- enabled
- enablerepo
- endmacro
- envrc
- exceptioned
- EXPECT_STREQ
- Falco
@@ -232,8 +234,10 @@ words:
- pyenv
- pyparsing
- qalloc
- qbsprofile
- queuable
- Raphson
- rcflags
- replayer
- rerere
- retriable

193
docs/build/advanced_conan.md vendored Normal file
View File

@@ -0,0 +1,193 @@
# Advanced Conan configuration
This document provides advanced instructions for setting up and configuring Conan for `xrpld` development: custom profiles, the lockfile, patched recipes, and profile tweaks.
## Custom profile
If the default profile does not work for you and you do not yet have a Conan
profile, you can create one by running:
```bash
conan profile detect
```
You may need to make changes to the profile to suit your environment. You can
refer to the provided `conan/profiles/default` profile for inspiration, and you
may also need to apply the required [tweaks](#conan-profile-tweaks) to this
default profile.
## Conan lockfile
To achieve reproducible dependencies, we use a [Conan lockfile](https://docs.conan.io/2/tutorial/versioning/lockfiles.html),
which has to be updated every time dependencies change.
Please see the [instructions on how to regenerate the lockfile](../../conan/lockfile/README.md).
## Patched recipes
Occasionally, we need patched recipes or recipes not present in Conan Center.
We maintain a fork of the Conan Center Index
[here](https://github.com/XRPLF/conan-center-index/) containing the modified and newly added recipes.
To ensure our patched recipes are used, you must add our Conan remote at a
higher index than the default Conan Center remote, so it is consulted first. You
can do this by running:
```bash
conan remote add --index 0 --force xrplf https://conan.ripplex.io
```
Alternatively, you can pull our recipes from the repository and export them locally:
```bash
# Define which recipes to export.
recipes=('abseil' 'ed25519' 'mpt-crypto' 'openssl' 'secp256k1' 'snappy' 'soci' 'wasm-xrplf' 'wasmi')
# Selectively check out the recipes from our CCI fork.
cd external
mkdir -p conan-center-index
cd conan-center-index
git init
git remote add origin git@github.com:XRPLF/conan-center-index.git
git sparse-checkout init
for recipe in "${recipes[@]}"; do
echo "Checking out recipe '${recipe}'..."
git sparse-checkout add recipes/${recipe}
done
git fetch origin master
git checkout master
./export_all.sh
cd ../../
```
In the case we switch to a newer version of a dependency that still requires a
patch or add a new dependency, it will be necessary for you to pull in the changes and re-export the
updated dependencies with the newer version. However, if we switch to a newer
version that no longer requires a patch, no action is required on your part, as
the new recipe will be automatically pulled from the official Conan Center.
> [!NOTE]
> You might need to add `--lockfile=""` to your `conan install` command
> to avoid automatic use of the existing `conan.lock` file when you run
> `conan export` manually on your machine
>
> This is not recommended though, as you might end up using different revisions of recipes.
## Conan profile tweaks
### Missing compiler version
If you see an error similar to the following after running `conan profile show`:
```text
ERROR: Invalid setting '17' is not a valid 'settings.compiler.version' value.
Possible values are ['5.0', '5.1', '6.0', '6.1', '7.0', '7.3', '8.0', '8.1',
'9.0', '9.1', '10.0', '11.0', '12.0', '13', '13.0', '13.1', '14', '14.0', '15',
'15.0', '16', '16.0']
Read "http://docs.conan.io/2/knowledge/faq.html#error-invalid-setting"
```
you need to create `$(conan config home)/settings_user.yml` file if it doesn't exist and add the required version number(s)
to the `version` array specific for your compiler. For example:
```yaml
compiler:
apple-clang:
version: ["17.0"]
```
### Multiple compilers
If you have multiple compilers installed, make sure to select the one to use in
your default Conan configuration **before** running `conan profile detect`, by
setting the `CC` and `CXX` environment variables.
For example, if you are running MacOS and have [homebrew
LLVM@18](https://formulae.brew.sh/formula/llvm@18), and want to use it as a
compiler in the new Conan profile:
```bash
export CC=$(brew --prefix llvm@18)/bin/clang
export CXX=$(brew --prefix llvm@18)/bin/clang++
conan profile detect
```
You should also explicitly set the path to the compiler in the profile file,
which helps to avoid errors when `CC` and/or `CXX` are set and disagree with the
selected Conan profile. For example:
```text
[conf]
tools.build:compiler_executables={'c':'/usr/bin/gcc','cpp':'/usr/bin/g++'}
```
### Multiple profiles
You can manage multiple Conan profiles in the directory
`$(conan config home)/profiles`, for example renaming `default` to a different
name and then creating a new `default` profile for a different compiler.
### Select language
The default profile created by Conan will typically select different C++ dialect
than C++23 used by this project. You should set `23` in the profile line
starting with `compiler.cppstd=`. For example:
```bash
sed -i.bak -e 's|^compiler\.cppstd=.*$|compiler.cppstd=23|' $(conan config home)/profiles/default
```
### Select standard library in Linux
**Linux** developers will commonly have a default Conan [profile][] that
compiles with GCC and links with libstdc++. If you are linking with libstdc++
(see profile setting `compiler.libcxx`), then you will need to choose the
`libstdc++11` ABI:
```bash
sed -i.bak -e 's|^compiler\.libcxx=.*$|compiler.libcxx=libstdc++11|' $(conan config home)/profiles/default
```
### Select architecture and runtime in Windows
**Windows** developers may need to use the x64 native build tools. An easy way
to do that is to run the shortcut "x64 Native Tools Command Prompt" for the
version of Visual Studio that you have installed.
Windows developers must also build `xrpld` and its dependencies for the x64
architecture:
```bash
sed -i.bak -e 's|^arch=.*$|arch=x86_64|' $(conan config home)/profiles/default
```
**Windows** developers also must select static runtime:
```bash
sed -i.bak -e 's|^compiler\.runtime=.*$|compiler.runtime=static|' $(conan config home)/profiles/default
```
## Add a Dependency
If you want to experiment with a new package, follow these steps:
1. Search for the package on [Conan Center](https://conan.io/center/).
2. Modify [`conanfile.py`](../../conanfile.py):
- Add a version of the package to the `requires` property.
- Change any default options for the package by adding them to the
`default_options` property (with syntax `'$package:$option': $value`).
3. Regenerate the [Conan lockfile](../../conan/lockfile/README.md) so the new
dependency is captured:
```bash
./conan/lockfile/regenerate.sh
```
4. Modify [`CMakeLists.txt`](../../CMakeLists.txt):
- Add a call to `find_package($package REQUIRED)`.
- Link a library from the package to the target `xrpl_libs`
(search for the existing call to `target_link_libraries(xrpl_libs INTERFACE ...)`).
5. Start coding! Don't forget to include whatever headers you need from the package.
[profile]: https://docs.conan.io/2/reference/config_files/profiles.html

2
docs/build/conan.md vendored
View File

@@ -115,7 +115,7 @@ By default, Conan will use the profile named "default".
[find_package]: https://cmake.org/cmake/help/latest/command/find_package.html
[pcf]: https://cmake.org/cmake/help/latest/manual/cmake-packages.7.html#package-configuration-file
[prefix_path]: https://cmake.org/cmake/help/latest/variable/CMAKE_PREFIX_PATH.html
[profile]: https://docs.conan.io/en/latest/reference/profiles.html
[profile]: https://docs.conan.io/2/reference/config_files/profiles.html
[pvf]: https://cmake.org/cmake/help/latest/manual/cmake-packages.7.html#package-version-file
[runtime]: https://cmake.org/cmake/help/latest/variable/CMAKE_MSVC_RUNTIME_LIBRARY.html
[search]: https://cmake.org/cmake/help/latest/command/find_package.html#search-procedure

View File

@@ -1,69 +1,73 @@
Our [build instructions][BUILD.md] assume you have a C++ development
environment complete with Git, Python, Conan, CMake, and a C++ compiler.
This document exists to help readers set one up on any of the Big Three
platforms: Linux, macOS, or Windows.
As an alternative to system packages, the Nix development shell can be used to provide a development environment. See [using nix development shell](./nix.md) for more details.
This document explains how to set one up.
[BUILD.md]: ../../BUILD.md
## Linux
## Tested compiler versions
Package ecosystems vary across Linux distributions,
so there is no one set of instructions that will work for every Linux user.
The instructions below are written for Debian 12 (Bookworm).
`xrpld` is built in the **C++23** dialect by default.
Make sure your toolchain is recent enough — the compiler versions currently tested in CI are:
```
export GCC_RELEASE=12
sudo apt update
sudo apt install --yes gcc-${GCC_RELEASE} g++-${GCC_RELEASE} python3-pip \
python-is-python3 python3-venv python3-dev curl wget ca-certificates \
git build-essential cmake ninja-build libc6-dev
sudo pip install --break-system-packages conan
| Compiler | Version |
| ----------- | ------- |
| GCC | 15.2 |
| Clang | 22 |
| Apple Clang | 17 |
| MSVC | 19.44 |
sudo update-alternatives --install /usr/bin/cc cc /usr/bin/gcc-${GCC_RELEASE} 999
sudo update-alternatives --install \
/usr/bin/gcc gcc /usr/bin/gcc-${GCC_RELEASE} 100 \
--slave /usr/bin/g++ g++ /usr/bin/g++-${GCC_RELEASE} \
--slave /usr/bin/gcc-ar gcc-ar /usr/bin/gcc-ar-${GCC_RELEASE} \
--slave /usr/bin/gcc-nm gcc-nm /usr/bin/gcc-nm-${GCC_RELEASE} \
--slave /usr/bin/gcc-ranlib gcc-ranlib /usr/bin/gcc-ranlib-${GCC_RELEASE} \
--slave /usr/bin/gcov gcov /usr/bin/gcov-${GCC_RELEASE} \
--slave /usr/bin/gcov-tool gcov-tool /usr/bin/gcov-tool-${GCC_RELEASE} \
--slave /usr/bin/gcov-dump gcov-dump /usr/bin/gcov-dump-${GCC_RELEASE} \
--slave /usr/bin/lto-dump lto-dump /usr/bin/lto-dump-${GCC_RELEASE}
sudo update-alternatives --auto cc
sudo update-alternatives --auto gcc
LLVM tools (`clang-tidy` and `clang-format`) are also pinned to version 22.
Older compilers may fail to build the latest `develop` code: the codebase now
relies on C++23 features and has been adjusted for `clang-tidy`.
If the latest code doesn't build for you, update your build toolchain first.
## Linux and macOS
The **recommended way** to get a development environment on Linux and macOS is
the Nix development shell. It provides the exact tooling used in CI — `git`,
`python`, `conan`, `cmake`, `clang-tidy`, `clang-format`, and everything else —
with a single command and without installing anything system-wide:
```bash
nix --experimental-features 'nix-command flakes' develop
```
If you use different Linux distribution, hope the instruction above can guide
you in the right direction. We try to maintain compatibility with all recent
compiler releases, so if you use a rolling distribution like e.g. Arch or CentOS
then there is a chance that everything will "just work".
On **Linux**, Nix also provides the compiler (GCC). On **macOS**, the shell uses
your **system-wide Apple Clang** as the compiler, so you still need to manage
its version (see below).
## macOS
See [Using the Nix development shell](./nix.md) for installation and usage
details, including how to select a different compiler.
Open a Terminal and enter the below command to bring up a dialog to install
the command line developer tools.
Once it is finished, this command should return a version greater than the
minimum required (see [BUILD.md][]).
> [!NOTE]
> Using Nix is not mandatory. Any custom environment (Homebrew packages or
> anything else) will continue to work, but then it is up to you to keep it in
> sync with the environment used in CI. Nix unifies the development environment
> for everyone and synchronizes updates, which is why we recommend it.
```
### macOS: managing the Apple Clang version
Because the Nix shell uses the system-wide Apple Clang on macOS, the compiler
version is whatever your installed Xcode (or Command Line Tools) provides. The
following command should return a version greater than or equal to the
[minimum required](#tested-compiler-versions):
```bash
clang --version
```
### Install Xcode Specific Version (Optional)
If you develop other applications using XCode you might be consistently updating to the newest version of Apple Clang.
This will likely cause issues building xrpld. You may want to install a specific version of Xcode:
If you develop other applications using Xcode, you might be consistently
updating to the newest version of Apple Clang, which will likely cause issues
building xrpld. You may want to install and pin a specific version of Xcode:
1. **Download Xcode**
- Visit [Apple Developer Downloads](https://developer.apple.com/download/more/)
- Sign in with your Apple Developer account
- Search for an Xcode version that includes **Apple Clang (Expected Version)**
- Search for an Xcode version that includes the expected Apple Clang version
- Download the `.xip` file
2. **Install and Configure Xcode**
2. **Install and configure Xcode**
```bash
# Extract the .xip file and rename for version management
@@ -79,62 +83,28 @@ This will likely cause issues building xrpld. You may want to install a specific
export DEVELOPER_DIR=/Applications/Xcode_16.2.app/Contents/Developer
```
The command line developer tools should include Git too:
## Windows
```
git --version
```
Nix is not available on Windows, so the required tools have to be installed
manually:
Install [Homebrew][],
use it to install [pyenv][],
use it to install Python,
and use it to install Conan:
- [Visual Studio 2022](https://visualstudio.microsoft.com/) with the
**"Desktop development with C++"** workload — this provides MSVC and the
"x64 Native Tools Command Prompt".
- [Git for Windows](https://git-scm.com/download/win)
- [Python 3.11](https://www.python.org/downloads/), or higher
- [Conan 2.17](https://conan.io/downloads.html), or higher
- [CMake 3.22](https://cmake.org/download/), or higher
[Homebrew]: https://brew.sh/
[pyenv]: https://github.com/pyenv/pyenv
```
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
brew update
brew install xz
brew install pyenv
pyenv install 3.11
pyenv global 3.11
eval "$(pyenv init -)"
pip install 'conan'
```
Install CMake with Homebrew too:
```
brew install cmake
```
> [!NOTE]
> Windows is used for development only and is not recommended for production.
## Clang-tidy
Clang-tidy is required to run static analysis checks locally (see [CONTRIBUTING.md](../../CONTRIBUTING.md)).
It is not required to build the project. Currently this project uses clang-tidy version 21.
`clang-tidy` is required to run static analysis checks locally (see
[CONTRIBUTING.md](../../CONTRIBUTING.md)). It is not required to build the
project. This project currently uses `clang-tidy` version 22.
### Linux
LLVM 21 is not available in the default Debian 12 (Bookworm) repositories.
Install it using the official LLVM apt installer:
```
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 21
sudo apt install --yes clang-tidy-21
```
Then use `run-clang-tidy-21` when running clang-tidy locally.
### macOS
Install LLVM 21 via Homebrew:
```
brew install llvm@21
```
Then use `run-clang-tidy` from the LLVM 21 Homebrew prefix when running clang-tidy locally.
On Linux and macOS, the [Nix development shell](./nix.md) provides `clang-tidy`
22 out of the box — run it via `run-clang-tidy`. No separate installation is
needed.

45
docs/build/nix.md vendored
View File

@@ -2,9 +2,12 @@
This guide explains how to use Nix to set up a reproducible development environment for xrpld. Using Nix eliminates the need to manually install utilities and ensures consistent tooling across different machines.
**The Nix development shell is the recommended way to develop xrpld.** It unifies the development environment for everyone and synchronizes updates: the same tooling and compiler versions are used both here and in CI. Any custom environment (Homebrew packages or anything else) will continue to work, but then it is up to you to keep it in sync with the environment used in CI.
## 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
- **No system pollution**: Dependencies are isolated and don't affect your system packages
- **Multiple compiler versions**: Easily switch between different GCC and Clang versions
- **Quick setup**: Get started with a single command
@@ -28,11 +31,22 @@ This will:
- Download and set up all required development tools (CMake, Ninja, Conan, etc.)
- Configure the appropriate compiler for your platform:
- **macOS**: Apple Clang (default system compiler)
- **Linux**: GCC 15
- **Linux**: GCC 15.2 (provided by Nix)
- **macOS**: Apple Clang (your system compiler)
The first time you run this command, it will take a few minutes to download and build the environment. Subsequent runs will be much faster.
### Platform notes
- **Linux**: `nix develop` gives you a shell with all the tooling necessary to
develop xrpld and with GCC 15.2 (also provided by Nix). There are no caveats.
- **macOS**: `nix develop` gives you a full environment too. The compiler is
your system-wide Apple Clang, while every other tool — including Conan — is
provided by Nix. Conan has no binary in the Nix cache for macOS, so it is
built from source the first time you enter the shell, which makes the initial
setup slower (this is handled automatically; see
[`nix/devshell.nix`](../../nix/devshell.nix)).
> [!TIP]
> To avoid typing `--experimental-features 'nix-command flakes'` every time, you can permanently enable flakes by creating `~/.config/nix/nix.conf`:
>
@@ -51,7 +65,7 @@ The first time you run this command, it will take a few minutes to download and
A compiler can be chosen by providing its name with the `.#` prefix, e.g. `nix develop .#gcc15`.
Use `nix flake show` to see all the available development shells.
Use `nix develop .#no_compiler` to use the compiler from your system.
Use `nix develop .#no-compiler` to use the compiler from your system.
### Example Usage
@@ -68,12 +82,28 @@ nix develop
### Using a different shell
`nix develop` opens bash by default. If you want to use another shell this could be done by adding `-c` flag. For example:
`nix develop` opens bash by default. To use another shell, pass it with the `-c` flag — this works with any shell, e.g. `zsh` or `fish`:
```bash
# Use zsh
nix develop -c zsh
# Use fish
nix develop -c fish
# Use your login shell
nix develop -c "$SHELL"
```
> [!WARNING]
> Your shell's interactive startup files (e.g. `config.fish`, `.zshrc`) may prepend other directories — most commonly Homebrew — to `$PATH`, which can shadow the tools provided by the Nix shell. After entering, verify that tools resolve into the Nix store:
>
> ```bash
> command -v cmake # should print a /nix/store/... path
> ```
>
> If it doesn't, either adjust your shell configuration so it doesn't override `$PATH`, or use [direnv](#automatic-activation-with-direnv) (below), which loads the environment _after_ your shell config and so takes precedence regardless of the shell you use.
## Building xrpld with Nix
Once inside the Nix development shell, follow the standard [build instructions](../../BUILD.md#steps). The Nix shell provides all necessary tools (CMake, Ninja, Conan, etc.).
@@ -82,6 +112,8 @@ Once inside the Nix development shell, follow the standard [build instructions](
[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.
This is also the most robust way to use the environment from **any shell** (bash, zsh, fish, …): direnv stays in your current shell and loads the environment _after_ your shell's startup files have run, so the Nix-provided tools take precedence over anything your shell configuration adds to `$PATH`. To use it, install direnv for your shell, then add an `.envrc` containing `use flake` at the repository root and run `direnv allow`.
## Conan and Prebuilt Packages
Please note that there is no guarantee that binaries from conan cache will work when using nix. If you encounter any errors, please use `--build '*'` to force conan to compile everything from source:
@@ -93,3 +125,8 @@ conan install .. --output-folder . --build '*' --settings build_type=Release
## Updating `flake.lock` file
To update `flake.lock` to the latest revision use `nix flake update` command.
## Troubleshooting
See [Troubleshooting Nix problems](./nix_troubleshooting.md) for common issues,
such as `nix develop` failing inside Git worktrees.

61
docs/build/nix_troubleshooting.md vendored Normal file
View File

@@ -0,0 +1,61 @@
# Troubleshooting Nix problems
Common issues encountered when using the [Nix development shell](./nix.md), and
how to resolve them.
## Git worktrees
If `nix develop` fails with an error like:
```
error:
… while fetching the input 'git+file:///path/to/rippled'
error: opening Git repository "/path/to/rippled": unsupported extension name extensions.relativeworktrees (libgit2 error code = 6)
```
then your Nix is linked against a libgit2 older than **1.9.4**. Git 2.48+ writes
the `extensions.relativeWorktrees` config entry when a worktree is created with
relative paths (`git worktree add --relative-paths`, or with
`worktree.useRelativePaths=true`), and older libgit2 versions refuse to open a
repository that uses it. Nix uses libgit2 to read the flake, so evaluation
fails.
> [!IMPORTANT]
> This entry is written to the **shared** repository config, so once any
> relative worktree exists, `nix develop` fails in the main checkout too — not
> just inside the worktree.
### Workarounds
These work today, with any Nix version:
- bypass libgit2 with a `path:` flakeref: `nix develop "path:$PWD"`
(note: this copies the working tree to the store and ignores `.gitignore`); or
- create worktrees with absolute paths (omit `--relative-paths`); or
- clear the extension if you don't need relative worktrees:
`git config --unset extensions.relativeWorktrees`.
### Permanent fix
The fix is in [libgit2 1.9.4](https://github.com/libgit2/libgit2/releases/tag/v1.9.4),
so the real solution is a Nix that links against libgit2 `1.9.4` or newer. Check
which version yours links against:
```bash
nix-store -qR "$(readlink -f "$(command -v nix)")" | grep libgit2
```
> [!WARNING]
> `nix upgrade-nix` does **not** help yet. It installs the build from the
> official [`nix-fallback-paths`](https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/installer/tools/nix-fallback-paths.nix),
> which is still linked against libgit2 `1.9.2` — there is no new upstream Nix
> release with the fix. (On some systems that build is even the exact store path
> you already have, making the upgrade a no-op.)
nixpkgs has already rebuilt Nix against the fixed libgit2 (e.g. `nix-2.34.7+1`),
so the cleanest path is to reinstall Nix using your usual installation method
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.

13
flake.lock generated
View File

@@ -2,17 +2,18 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1780243769,
"narHash": "sha256-x5UQuRsH3MqI0U9afaXSNqzTPSeZlRLvFAav2Ux1pNw=",
"lastModified": 1781173989,
"narHash": "sha256-fnzKKPvS+oieI/pTzotA5tkoM47EB1NpaBcgk4R97hE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "331800de5053fcebacf6813adb5db9c9dca22a0c",
"rev": "8c91a71d13451abc40eb9dae8910f972f979852f",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-unstable",
"type": "indirect"
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-custom-glibc": {

View File

@@ -1,7 +1,7 @@
{
description = "Nix related things for xrpld";
inputs = {
nixpkgs.url = "nixpkgs/nixos-unstable";
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
# nixpkgs snapshot (2020-06-30) that shipped glibc 2.31 as the primary
# version — matches the system libc on Ubuntu 20.04 LTS. Imported
# manually (flake = false) because this revision predates nixpkgs'

View File

@@ -1,248 +0,0 @@
#pragma once
#include <xrpl/basics/contract.h>
#include <boost/outcome.hpp>
#include <stdexcept>
namespace xrpl {
/** Expected is an approximation of std::expected (hoped for in C++23)
See: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0323r10.html
The implementation is entirely based on boost::outcome_v2::result.
*/
// Exception thrown by an invalid access to Expected.
struct BadExpectedAccess : public std::runtime_error
{
BadExpectedAccess() : runtime_error("bad expected access")
{
}
};
namespace detail {
// Custom policy for Expected. Always throw on an invalid access.
struct ThrowPolicy : public boost::outcome_v2::policy::base
{
template <class Impl>
static constexpr void
// NOLINTNEXTLINE(readability-identifier-naming)
wide_value_check(Impl&& self)
{
if (!base::_has_value(std::forward<Impl>(self)))
Throw<BadExpectedAccess>();
}
template <class Impl>
static constexpr void
// NOLINTNEXTLINE(readability-identifier-naming)
wide_error_check(Impl&& self)
{
if (!base::_has_error(std::forward<Impl>(self)))
Throw<BadExpectedAccess>();
}
template <class Impl>
static constexpr void
// NOLINTNEXTLINE(readability-identifier-naming)
wide_exception_check(Impl&& self)
{
if (!base::_has_exception(std::forward<Impl>(self)))
Throw<BadExpectedAccess>();
}
};
} // namespace detail
// Definition of Unexpected, which is used to construct the unexpected
// return type of an Expected.
template <class E>
class Unexpected
{
public:
static_assert(!std::is_same_v<E, void>, "E must not be void");
Unexpected() = delete;
constexpr explicit Unexpected(E const& e) : val_(e)
{
}
constexpr explicit Unexpected(E&& e) : val_(std::move(e))
{
}
[[nodiscard]] constexpr E const&
value() const&
{
return val_;
}
constexpr E&
value() &
{
return val_;
}
constexpr E&&
value() &&
{
return std::move(val_);
}
[[nodiscard]] constexpr E const&&
value() const&&
{
return std::move(val_);
}
private:
E val_;
};
// Unexpected deduction guide that converts array to const*.
template <typename E, std::size_t N>
Unexpected(E (&)[N]) -> Unexpected<E const*>;
// Definition of Expected. All of the machinery comes from boost::result.
template <class T, class E>
class [[nodiscard]] Expected : private boost::outcome_v2::result<T, E, detail::ThrowPolicy>
{
using Base = boost::outcome_v2::result<T, E, detail::ThrowPolicy>;
public:
template <typename U>
requires std::convertible_to<U, T>
constexpr Expected(U&& r) : Base(boost::outcome_v2::in_place_type_t<T>{}, std::forward<U>(r))
{
}
template <typename U>
requires std::convertible_to<U, E> && (!std::is_reference_v<U>)
constexpr Expected(Unexpected<U> e)
: Base(boost::outcome_v2::in_place_type_t<E>{}, std::move(e.value()))
{
}
[[nodiscard]] constexpr bool
// NOLINTNEXTLINE(readability-identifier-naming)
has_value() const
{
return Base::has_value();
}
[[nodiscard]] constexpr T const&
value() const
{
return Base::value();
}
constexpr T&
value()
{
return Base::value();
}
[[nodiscard]] constexpr E const&
error() const&
{
return Base::error();
}
[[nodiscard]] constexpr E&
error() &
{
return Base::error();
}
[[nodiscard]] constexpr E&&
error() &&
{
return std::move(Base::error());
}
constexpr explicit
operator bool() const
{
return has_value();
}
// Add operator* and operator-> so the Expected API looks a bit more like
// what std::expected is likely to look like. See:
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0323r10.html
[[nodiscard]] constexpr T&
operator*()
{
return this->value();
}
[[nodiscard]] constexpr T const&
operator*() const
{
return this->value();
}
[[nodiscard]] constexpr T*
operator->()
{
return &this->value();
}
[[nodiscard]] constexpr T const*
operator->() const
{
return &this->value();
}
};
// Specialization of Expected<void, E>. Allows returning either success
// (without a value) or the reason for the failure.
template <class E>
class [[nodiscard]]
Expected<void, E> : private boost::outcome_v2::result<void, E, detail::ThrowPolicy>
{
using Base = boost::outcome_v2::result<void, E, detail::ThrowPolicy>;
public:
// The default constructor makes a successful Expected<void, E>.
// This aligns with std::expected behavior proposed in P0323R10.
constexpr Expected() : Base(boost::outcome_v2::success())
{
}
template <typename U>
requires std::convertible_to<U, E> && (!std::is_reference_v<U>)
constexpr Expected(Unexpected<U> e) : Base(E(std::move(e.value())))
{
}
[[nodiscard]] constexpr E const&
error() const&
{
return Base::error();
}
[[nodiscard]] constexpr E&
error() &
{
return Base::error();
}
[[nodiscard]] constexpr E&&
error() &&
{
return std::move(Base::error());
}
constexpr explicit
operator bool() const
{
return Base::has_value();
}
};
} // namespace xrpl

View File

@@ -408,33 +408,40 @@ public:
}
friend constexpr bool
operator<(Number const& x, Number const& y) noexcept
operator<(Number const& l, Number const& r) noexcept
{
bool const lneg = l.negative_;
bool const rneg = r.negative_;
// If the two amounts have different signs (zero is treated as positive)
// then the comparison is true iff the left is negative.
bool const lneg = x.negative_;
bool const rneg = y.negative_;
if (lneg != rneg)
return lneg;
// Both have same sign and the left is zero: the right must be
// greater than 0.
if (x.mantissa_ == 0)
return y.mantissa_ > 0;
// Both have same sign and the left is zero: both must be non-negative.
// If the right is greater than 0, then it is larger, so the comparison is true.
if (l.mantissa_ == 0)
return r.mantissa_ > 0;
// Both have same sign, the right is zero and the left is non-zero.
if (y.mantissa_ == 0)
// Both have same sign, the right is zero and the left is non-zero, so the left must be
// positive, and thus is larger, so the comparison is false.
if (r.mantissa_ == 0)
return false;
// Both have the same sign, compare by exponents:
if (x.exponent_ > y.exponent_)
if (l.exponent_ > r.exponent_)
return lneg;
if (x.exponent_ < y.exponent_)
if (l.exponent_ < r.exponent_)
return !lneg;
// If equal exponents, compare mantissas
return x.mantissa_ < y.mantissa_;
// If equal signs and exponents, compare mantissas.
if (lneg)
{
// If negative, the operator is reversed.
return l.mantissa_ > r.mantissa_;
}
return l.mantissa_ < r.mantissa_;
}
/** Return the sign of the amount */

View File

@@ -11,6 +11,7 @@
#include <cstdint>
#include <optional>
#include <string>
#include <string_view>
#include <type_traits>
namespace xrpl {
@@ -95,13 +96,7 @@ strUnHex(std::size_t strSize, Iterator begin, Iterator end)
}
inline std::optional<Blob>
strUnHex(std::string const& strSrc)
{
return strUnHex(strSrc.size(), strSrc.cbegin(), strSrc.cend());
}
inline std::optional<Blob>
strViewUnHex(std::string_view strSrc)
strUnHex(std::string_view strSrc)
{
return strUnHex(strSrc.size(), strSrc.cbegin(), strSrc.cend());
}

View File

@@ -36,6 +36,7 @@
#include <cstdint>
#include <string>
#include <string_view>
namespace xrpl {
@@ -43,7 +44,7 @@ std::string
base64Encode(std::uint8_t const* data, std::size_t len);
inline std::string
base64Encode(std::string const& s)
base64Encode(std::string_view s)
{
return base64Encode(reinterpret_cast<std::uint8_t const*>(s.data()), s.size());
}

View File

@@ -5,7 +5,6 @@
#pragma once
#include <xrpl/basics/Expected.h>
#include <xrpl/basics/Slice.h>
#include <xrpl/basics/contract.h>
#include <xrpl/basics/hardened_hash.h>
@@ -20,6 +19,7 @@
#include <algorithm>
#include <array>
#include <cstring>
#include <expected>
#include <type_traits>
namespace xrpl {
@@ -177,7 +177,7 @@ private:
BadChar,
};
constexpr Expected<decltype(data_), ParseResult>
constexpr std::expected<decltype(data_), ParseResult>
parseFromStringView(std::string_view sv) noexcept
{
// Local lambda that converts a single hex char to four bits and
@@ -216,7 +216,7 @@ private:
}
if (sv.size() != size() * 2)
return Unexpected(ParseResult::BadLength);
return std::unexpected(ParseResult::BadLength);
std::size_t i = 0u;
auto in = sv.begin();
@@ -227,7 +227,7 @@ private:
{
if (auto const result = hexCharToUInt(*in++, shift, accum);
result != ParseResult::Okay)
return Unexpected(result);
return std::unexpected(result);
}
ret[i++] = accum;
}

View File

@@ -1,12 +1,13 @@
#pragma once
#include <string>
#include <string_view>
namespace xrpl {
template <class Stream, class Iter>
Stream&
join(Stream& s, Iter iter, Iter end, std::string const& delimiter)
join(Stream& s, Iter iter, Iter end, std::string_view delimiter)
{
if (iter == end)
return s;

View File

@@ -7,8 +7,11 @@
#include <array>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <new>
#include <optional>
#include <span>
#include <type_traits>
namespace beast {

View File

@@ -3,6 +3,7 @@
#include <xrpl/beast/insight/CounterImpl.h>
#include <memory>
#include <utility>
namespace beast::insight {
@@ -29,7 +30,7 @@ public:
factory function in the Collector interface.
@see Collector.
*/
explicit Counter(std::shared_ptr<CounterImpl> const& impl) : impl_(impl)
explicit Counter(std::shared_ptr<CounterImpl> impl) : impl_(std::move(impl))
{
}

View File

@@ -4,6 +4,7 @@
#include <chrono>
#include <memory>
#include <utility>
namespace beast::insight {
@@ -31,7 +32,7 @@ public:
factory function in the Collector interface.
@see Collector.
*/
explicit Event(std::shared_ptr<EventImpl> const& impl) : impl_(impl)
explicit Event(std::shared_ptr<EventImpl> impl) : impl_(std::move(impl))
{
}

View File

@@ -3,6 +3,7 @@
#include <xrpl/beast/insight/GaugeImpl.h>
#include <memory>
#include <utility>
namespace beast::insight {
@@ -31,7 +32,7 @@ public:
factory function in the Collector interface.
@see Collector.
*/
explicit Gauge(std::shared_ptr<GaugeImpl> const& impl) : impl_(impl)
explicit Gauge(std::shared_ptr<GaugeImpl> impl) : impl_(std::move(impl))
{
}

View File

@@ -3,6 +3,7 @@
#include <xrpl/beast/insight/HookImpl.h>
#include <memory>
#include <utility>
namespace beast::insight {
@@ -20,7 +21,7 @@ public:
factory function in the Collector interface.
@see Collector.
*/
explicit Hook(std::shared_ptr<HookImpl> const& impl) : impl_(impl)
explicit Hook(std::shared_ptr<HookImpl> impl) : impl_(std::move(impl))
{
}

View File

@@ -3,6 +3,7 @@
#include <xrpl/beast/insight/MeterImpl.h>
#include <memory>
#include <utility>
namespace beast::insight {
@@ -28,7 +29,7 @@ public:
factory function in the Collector interface.
@see Collector.
*/
explicit Meter(std::shared_ptr<MeterImpl> const& impl) : impl_(impl)
explicit Meter(std::shared_ptr<MeterImpl> impl) : impl_(std::move(impl))
{
}

View File

@@ -41,7 +41,7 @@ private:
public:
template <class = void>
explicit Selector(ModeT mode, std::string const& pattern = "");
explicit Selector(ModeT mode, std::string pattern = "");
template <class = void>
bool
@@ -51,9 +51,9 @@ public:
//------------------------------------------------------------------------------
template <class>
Selector::Selector(ModeT mode, std::string const& pattern) : mode_(mode), pat_(pattern)
Selector::Selector(ModeT mode, std::string pattern) : mode_(mode), pat_(std::move(pattern))
{
if (mode_ == ModeT::Automatch && pattern.empty())
if (mode_ == ModeT::Automatch && pat_.empty())
mode_ = ModeT::All;
}

View File

@@ -11,6 +11,8 @@
// Macros below are copied from antithesis_sdk.h and slightly simplified
// The duplication is because Visual Studio 2019 cannot compile that header
// even with the option -Zc:__cplusplus added.
// NOTE: cond must not contain bare commas outside () or []. Commas inside {}
// are not protected by the preprocessor and would be parsed as extra arguments.
#define ALWAYS(cond, message, ...) assert((message) && (cond))
#define ALWAYS_OR_UNREACHABLE(cond, message) assert((message) && (cond))
#define SOMETIMES(cond, message, ...)
@@ -22,6 +24,8 @@
#define XRPL_ASSERT_PARTS(cond, function, description, ...) \
XRPL_ASSERT(cond, function " : " description)
#define XRPL_ASSERT_IF(guard, cond, message) XRPL_ASSERT(!(guard) || (cond), message)
// How to use the instrumentation macros:
//
// * XRPL_ASSERT if cond must be true but the line might not be reached during
@@ -29,6 +33,14 @@
// * XRPL_ASSERT_PARTS is for convenience, and works like XRPL_ASSERT, but
// splits the message param into "function" and "description", then joins
// them with " : " before passing to XRPL_ASSERT.
// * XRPL_ASSERT_IF(guard, cond, message) asserts the implication
// `guard => cond`: it can only fail when guard is true (e.g. an amendment
// is enabled) and cond is false. Unlike `if (guard) XRPL_ASSERT(...)`, the
// assertion site is always evaluated, so the fuzzer registers it
// unconditionally; cond itself is short-circuited and only evaluated when
// guard is true. NOTE: do not rely on side effects in guard — in release
// builds the assertion body is stripped, and the compiler may optimize away
// a side-effect-free guard entirely.
// * ALWAYS if cond must be true _and_ the line must be reached during fuzzing.
// Same like `assert` in normal use.
// * REACHABLE if the line must be reached during fuzzing

View File

@@ -0,0 +1,180 @@
#pragma once
namespace xrpl {
struct Sections
{
static constexpr auto kAmendments = "amendments";
static constexpr auto kAmendmentMajorityTime = "amendment_majority_time";
static constexpr auto kBetaRpcApi = "beta_rpc_api";
static constexpr auto kClusterNodes = "cluster_nodes";
static constexpr auto kCompression = "compression";
static constexpr auto kCrawl = "crawl";
static constexpr auto kDatabasePath = "database_path";
static constexpr auto kDebugLogfile = "debug_logfile";
static constexpr auto kElbSupport = "elb_support";
static constexpr auto kFeatures = "features";
static constexpr auto kFeeDefault = "fee_default";
static constexpr auto kFetchDepth = "fetch_depth";
static constexpr auto kHashrouter = "hashrouter";
static constexpr auto kImportNodeDatabase = "import_db";
static constexpr auto kInsight = "insight";
static constexpr auto kIoWorkers = "io_workers";
static constexpr auto kIps = "ips";
static constexpr auto kIpsFixed = "ips_fixed";
static constexpr auto kLedgerHistory = "ledger_history";
static constexpr auto kLedgerReplay = "ledger_replay";
static constexpr auto kLedgerTxTables = "ledger_tx_tables";
static constexpr auto kMaxTransactions = "max_transactions";
static constexpr auto kNetworkId = "network_id";
static constexpr auto kNetworkQuorum = "network_quorum";
static constexpr auto kNodeDatabase = "node_db";
static constexpr auto kNodeSeed = "node_seed";
static constexpr auto kNodeSize = "node_size";
static constexpr auto kOverlay = "overlay";
static constexpr auto kPathSearch = "path_search";
static constexpr auto kPathSearchFast = "path_search_fast";
static constexpr auto kPathSearchMax = "path_search_max";
static constexpr auto kPathSearchOld = "path_search_old";
static constexpr auto kPeerPrivate = "peer_private";
static constexpr auto kPeersInMax = "peers_in_max";
static constexpr auto kPeersMax = "peers_max";
static constexpr auto kPeersOutMax = "peers_out_max";
static constexpr auto kPerf = "perf";
static constexpr auto kPortGrpc = "port_grpc";
static constexpr auto kPortPeer = "port_peer";
static constexpr auto kPortRpc = "port_rpc";
static constexpr auto kPortWs = "port_ws";
static constexpr auto kPortWssAdmin = "port_wss_admin";
static constexpr auto kPrefetchWorkers = "prefetch_workers";
static constexpr auto kReduceRelay = "reduce_relay";
static constexpr auto kRelationalDb = "relational_db";
static constexpr auto kRelayProposals = "relay_proposals";
static constexpr auto kRelayValidations = "relay_validations";
static constexpr auto kRpcStartup = "rpc_startup";
static constexpr auto kServer = "server";
static constexpr auto kServerDomain = "server_domain";
static constexpr auto kSigningSupport = "signing_support";
static constexpr auto kSntp = "sntp_servers";
static constexpr auto kSqdb = "sqdb";
static constexpr auto kSqlite = "sqlite";
static constexpr auto kSslVerify = "ssl_verify";
static constexpr auto kSslVerifyDir = "ssl_verify_dir";
static constexpr auto kSslVerifyFile = "ssl_verify_file";
static constexpr auto kSweepInterval = "sweep_interval";
static constexpr auto kTransactionQueue = "transaction_queue";
static constexpr auto kValidationSeed = "validation_seed";
static constexpr auto kValidatorKeys = "validator_keys";
static constexpr auto kValidatorKeyRevocation = "validator_key_revocation";
static constexpr auto kValidatorListKeys = "validator_list_keys";
static constexpr auto kValidatorListSites = "validator_list_sites";
static constexpr auto kValidatorListThreshold = "validator_list_threshold";
static constexpr auto kValidatorToken = "validator_token";
static constexpr auto kValidators = "validators";
static constexpr auto kValidatorsFile = "validators_file";
static constexpr auto kVetoAmendments = "veto_amendments";
static constexpr auto kVl = "vl";
static constexpr auto kVoting = "voting";
static constexpr auto kWorkers = "workers";
};
struct Keys
{
static constexpr auto kAccountReserve = "account_reserve";
static constexpr auto kAddress = "address";
static constexpr auto kAdmin = "admin";
static constexpr auto kAdminPassword = "admin_password";
static constexpr auto kAdminUser = "admin_user";
static constexpr auto kAdvisoryDelete = "advisory_delete";
static constexpr auto kAgeThresholdSeconds = "age_threshold_seconds";
static constexpr auto kBackOff = "backOff";
static constexpr auto kBackOffMilliseconds = "back_off_milliseconds";
static constexpr auto kBackend = "backend";
static constexpr auto kBbtOptions = "bbt_options";
static constexpr auto kBgThreads = "bg_threads";
static constexpr auto kBlockSize = "block_size";
static constexpr auto kCacheAge = "cache_age";
static constexpr auto kCacheMb = "cache_mb";
static constexpr auto kCacheSize = "cache_size";
static constexpr auto kClientMaxWindowBits = "client_max_window_bits";
static constexpr auto kClientNoContextTakeover = "client_no_context_takeover";
static constexpr auto kCompressLevel = "compress_level";
static constexpr auto kCounts = "counts";
static constexpr auto kDeleteBatch = "delete_batch";
static constexpr auto kEarliestSeq = "earliest_seq";
static constexpr auto kFastLoad = "fast_load";
static constexpr auto kFileSizeMb = "file_size_mb";
static constexpr auto kFileSizeMult = "file_size_mult";
static constexpr auto kFilterBits = "filter_bits";
static constexpr auto kFilterFull = "filter_full";
static constexpr auto kHardSet = "hard_set";
static constexpr auto kHighThreads = "high_threads";
static constexpr auto kHoldTime = "hold_time";
static constexpr auto kIp = "ip";
static constexpr auto kJournalMode = "journal_mode";
static constexpr auto kJournalSizeLimit = "journal_size_limit";
static constexpr auto kLedgersInQueue = "ledgers_in_queue";
static constexpr auto kLimit = "limit";
static constexpr auto kLogInterval = "log_interval";
static constexpr auto kMaxDivergedTime = "max_diverged_time";
static constexpr auto kMaxLedgerCountsToStore = "max_ledger_counts_to_store";
static constexpr auto kMaxUnknownTime = "max_unknown_time";
static constexpr auto kMaximumTxnInLedger = "maximum_txn_in_ledger";
static constexpr auto kMaximumTxnPerAccount = "maximum_txn_per_account";
static constexpr auto kMemoryLevel = "memory_level";
static constexpr auto kMinLedgersToComputeSizeLimit = "min_ledgers_to_compute_size_limit";
static constexpr auto kMinimumEscalationMultiplier = "minimum_escalation_multiplier";
static constexpr auto kMinimumLastLedgerBuffer = "minimum_last_ledger_buffer";
static constexpr auto kMinimumQueueSize = "minimum_queue_size";
static constexpr auto kMinimumTxnInLedger = "minimum_txn_in_ledger";
static constexpr auto kMinimumTxnInLedgerStandalone = "minimum_txn_in_ledger_standalone";
static constexpr auto kNormalConsensusIncreasePercent = "normal_consensus_increase_percent";
static constexpr auto kNudbBlockSize = "nudb_block_size";
static constexpr auto kOnlineDelete = "online_delete";
static constexpr auto kOpenFiles = "open_files";
static constexpr auto kOptions = "options";
static constexpr auto kOverlay = "overlay";
static constexpr auto kOwnerReserve = "owner_reserve";
static constexpr auto kPageSize = "page_size";
static constexpr auto kPassword = "password";
static constexpr auto kPath = "path";
static constexpr auto kPermessageDeflate = "permessage_deflate";
static constexpr auto kPort = "port";
static constexpr auto kPrefix = "prefix";
static constexpr auto kProtocol = "protocol";
static constexpr auto kRecoveryWaitSeconds = "recovery_wait_seconds";
static constexpr auto kReferenceFee = "reference_fee";
static constexpr auto kRelayTime = "relay_time";
static constexpr auto kRetrySequencePercent = "retry_sequence_percent";
static constexpr auto kRqBundle = "rq_bundle";
static constexpr auto kSafetyLevel = "safety_level";
static constexpr auto kSecureGateway = "secure_gateway";
static constexpr auto kSendQueueLimit = "send_queue_limit";
static constexpr auto kServer = "server";
static constexpr auto kServerMaxWindowBits = "server_max_window_bits";
static constexpr auto kServerNoContextTakeover = "server_no_context_takeover";
static constexpr auto kSlowConsensusDecreasePercent = "slow_consensus_decrease_percent";
static constexpr auto kSslCert = "ssl_cert";
static constexpr auto kSslCertChain = "ssl_cert_chain";
static constexpr auto kSslChain = "ssl_chain";
static constexpr auto kSslCiphers = "ssl_ciphers";
static constexpr auto kSslClientCa = "ssl_client_ca";
static constexpr auto kSslKey = "ssl_key";
static constexpr auto kSynchronous = "synchronous";
static constexpr auto kTargetTxnInLedger = "target_txn_in_ledger";
static constexpr auto kTempStore = "temp_store";
static constexpr auto kTxEnable = "tx_enable";
static constexpr auto kTxMetrics = "tx_metrics";
static constexpr auto kTxMinPeers = "tx_min_peers";
static constexpr auto kTxRelayPercentage = "tx_relay_percentage";
static constexpr auto kType = "type";
static constexpr auto kUniversalCompaction = "universal_compaction";
static constexpr auto kUnl = "unl";
static constexpr auto kUseTxTables = "use_tx_tables";
static constexpr auto kUser = "user";
static constexpr auto kVpBaseSquelchEnable = "vp_base_squelch_enable";
static constexpr auto kVpBaseSquelchMaxSelectedPeers = "vp_base_squelch_max_selected_peers";
static constexpr auto kVpEnable = "vp_enable";
};
} // namespace xrpl

View File

@@ -1,6 +1,5 @@
#pragma once
#include <xrpl/basics/BasicConfig.h>
#include <xrpl/core/JobTypes.h>
#include <xrpl/json/json_value.h>
@@ -18,6 +17,7 @@ class Journal;
namespace xrpl {
class Application;
class Section;
namespace perf {
/**

View File

@@ -1,6 +1,7 @@
#pragma once
#include <string>
#include <string_view>
#include <vector>
namespace xrpl {
@@ -34,7 +35,7 @@ private:
static void
standard(std::string& strWord);
static int
wsrch(std::string const& strWord, int iMin, int iMax);
wsrch(std::string_view strWord, int iMin, int iMax);
static int
etob(std::string& strData, std::vector<std::string> vsHuman);

View File

@@ -93,7 +93,7 @@ public:
}
void
insert(std::shared_ptr<STTx const> const& txn);
insert(std::shared_ptr<STTx const> txn);
// Pops the next transaction on account that follows seqProx in the
// sort order. Normally called when a transaction is successfully

View File

@@ -1,6 +1,5 @@
#pragma once
#include <xrpl/basics/Expected.h>
#include <xrpl/basics/Log.h>
#include <xrpl/basics/Number.h>
#include <xrpl/beast/utility/Journal.h>
@@ -18,6 +17,8 @@
#include <xrpl/protocol/STAmount.h>
#include <xrpl/protocol/STLedgerEntry.h>
#include <expected>
namespace xrpl {
namespace detail {
@@ -741,7 +742,7 @@ ammPoolHolds(
* provided then they are used as the AMM token pair issues.
* Otherwise the missing issues are fetched from ammSle.
*/
Expected<std::tuple<STAmount, STAmount, STAmount>, TER>
std::expected<std::tuple<STAmount, STAmount, STAmount>, TER>
ammHolds(
ReadView const& view,
SLE const& ammSle,
@@ -801,14 +802,14 @@ initializeFeeAuctionVote(
* otherwise. Return tecINTERNAL if encountered an unexpected condition,
* for instance Liquidity Provider has more than one LPToken trustline.
*/
Expected<bool, TER>
std::expected<bool, TER>
isOnlyLiquidityProvider(ReadView const& view, Issue const& ammIssue, AccountID const& lpAccount);
/** Due to rounding, the LPTokenBalance of the last LP might
* not match the LP's trustline balance. If it's within the tolerance,
* update LPTokenBalance to match the LP's trustline balance.
*/
Expected<bool, TER>
std::expected<bool, TER>
verifyAndAdjustLPTokenBalance(
Sandbox& sb,
STAmount const& lpTokens,

View File

@@ -1,6 +1,5 @@
#pragma once
#include <xrpl/basics/Expected.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h>
@@ -9,6 +8,7 @@
#include <xrpl/protocol/STLedgerEntry.h>
#include <xrpl/protocol/TER.h>
#include <expected>
#include <set>
#include <vector>
@@ -91,7 +91,7 @@ isPseudoAccount(
* before using a field. The amendment check is **not** performed in
* createPseudoAccount.
*/
[[nodiscard]] Expected<SLE::pointer, TER>
[[nodiscard]] std::expected<SLE::pointer, TER>
createPseudoAccount(ApplyView& view, uint256 const& pseudoOwnerKey, SField const& ownerField);
/** Checks the destination and tag.

View File

@@ -4,6 +4,7 @@
#include <xrpl/protocol/Rules.h>
#include <xrpl/protocol/st.h>
#include <expected>
#include <string_view>
namespace xrpl {
@@ -397,7 +398,7 @@ struct LoanStateDeltas
nonNegative();
};
Expected<std::pair<LoanPaymentParts, LoanProperties>, TER>
std::expected<std::pair<LoanPaymentParts, LoanProperties>, TER>
tryOverpayment(
Rules const& rules,
Asset const& asset,
@@ -523,7 +524,7 @@ isRounded(Asset const& asset, Number const& value, std::int32_t scale);
// potential extra work at the end.
enum class LoanPaymentType { Regular = 0, Late, Full, Overpayment };
Expected<LoanPaymentParts, TER>
std::expected<LoanPaymentParts, TER>
loanMakePayment(
Asset const& asset,
ApplyView& view,

View File

@@ -53,7 +53,7 @@ public:
boost::system::error_code const& ecResult,
int iStatus,
std::string const& strData)> complete,
beast::Journal& j);
beast::Journal const& j);
static void
get(bool bSSL,
@@ -67,7 +67,7 @@ public:
boost::system::error_code const& ecResult,
int iStatus,
std::string const& strData)> complete,
beast::Journal& j);
beast::Journal const& j);
static void
request(
@@ -82,7 +82,7 @@ public:
boost::system::error_code const& ecResult,
int iStatus,
std::string const& strData)> complete,
beast::Journal& j);
beast::Journal const& j);
};
} // namespace xrpl

View File

@@ -1,6 +1,5 @@
#pragma once
#include <xrpl/basics/BasicConfig.h>
#include <xrpl/basics/Log.h>
#include <xrpl/basics/TaggedCache.ipp>
#include <xrpl/nodestore/Backend.h>
@@ -10,6 +9,10 @@
#include <condition_variable>
namespace xrpl {
class Section;
} // namespace xrpl
namespace xrpl::NodeStore {
/** Persistency layer for NodeObject

View File

@@ -1,12 +1,15 @@
#pragma once
#include <xrpl/basics/BasicConfig.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/nodestore/Backend.h>
#include <xrpl/nodestore/Scheduler.h>
#include <nudb/store.hpp>
namespace xrpl {
class Section;
} // namespace xrpl
namespace xrpl::NodeStore {
/** Base class for backend factories. */

View File

@@ -2,6 +2,8 @@
#include <xrpl/basics/TaggedCache.h>
#include <xrpl/basics/chrono.h>
#include <xrpl/config/BasicConfig.h>
#include <xrpl/config/Constants.h>
#include <xrpl/nodestore/Database.h>
namespace xrpl::NodeStore {
@@ -24,16 +26,16 @@ public:
{
std::optional<int> cacheSize, cacheAge;
if (config.exists("cache_size"))
if (config.exists(Keys::kCacheSize))
{
cacheSize = get<int>(config, "cache_size");
cacheSize = get<int>(config, Keys::kCacheSize);
if (cacheSize.value() < 0)
Throw<std::runtime_error>("Specified negative value for cache_size");
}
if (config.exists("cache_age"))
if (config.exists(Keys::kCacheAge))
{
cacheAge = get<int>(config, "cache_age");
cacheAge = get<int>(config, Keys::kCacheAge);
if (cacheAge.value() < 0)
Throw<std::runtime_error>("Specified negative value for cache_age");
}

View File

@@ -65,7 +65,7 @@ invalidAMMAssetPair(
std::optional<std::uint8_t>
ammAuctionTimeSlot(std::uint64_t current, STObject const& auctionSlot);
/** Return true if required AMM amendments are enabled
/** Return true if required AMM amendment is enabled
*/
bool
ammEnabled(Rules const&);

View File

@@ -1,6 +1,5 @@
#pragma once
#include <xrpl/basics/LocalValue.h>
#include <xrpl/basics/Number.h>
#include <xrpl/beast/utility/Zero.h>
@@ -179,36 +178,4 @@ to_string(IOUAmount const& amount);
IOUAmount
mulRatio(IOUAmount const& amt, std::uint32_t num, std::uint32_t den, bool roundUp);
// Since many uses of the number class do not have access to a ledger,
// getSTNumberSwitchover needs to be globally accessible.
bool
getSTNumberSwitchover();
void
setSTNumberSwitchover(bool v);
/** RAII class to set and restore the Number switchover.
*/
class NumberSO
{
bool saved_;
public:
~NumberSO()
{
setSTNumberSwitchover(saved_);
}
NumberSO(NumberSO const&) = delete;
NumberSO&
operator=(NumberSO const&) = delete;
explicit NumberSO(bool v) : saved_(getSTNumberSwitchover())
{
setSTNumberSwitchover(v);
}
};
} // namespace xrpl

View File

@@ -122,7 +122,6 @@ private:
std::optional<Rules> saved_;
};
class NumberSO;
class NumberMantissaScaleGuard;
bool
@@ -131,7 +130,6 @@ useRulesGuards(Rules const& rules);
void
createGuards(
Rules const& rules,
std::optional<NumberSO>& stNumberSO,
std::optional<CurrentTransactionRulesGuard>& rulesGuard,
std::optional<NumberMantissaScaleGuard>& mantissaScaleGuard);

View File

@@ -1,6 +1,5 @@
#pragma once
#include <xrpl/basics/Expected.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/PublicKey.h>
#include <xrpl/protocol/Rules.h>
@@ -11,6 +10,7 @@
#include <boost/container/flat_set.hpp>
#include <expected>
#include <functional>
namespace xrpl {
@@ -108,10 +108,10 @@ public:
@param rules The current ledger rules.
@return `true` if valid signature. If invalid, the error message string.
*/
Expected<void, std::string>
std::expected<void, std::string>
checkSign(Rules const& rules) const;
Expected<void, std::string>
std::expected<void, std::string>
checkBatchSign(Rules const& rules) const;
// SQL Functions with metadata.
@@ -138,19 +138,19 @@ private:
Will be *this more often than not.
@return `true` if valid signature. If invalid, the error message string.
*/
Expected<void, std::string>
std::expected<void, std::string>
checkSign(Rules const& rules, STObject const& sigObject) const;
Expected<void, std::string>
std::expected<void, std::string>
checkSingleSign(STObject const& sigObject) const;
Expected<void, std::string>
std::expected<void, std::string>
checkMultiSign(Rules const& rules, STObject const& sigObject) const;
Expected<void, std::string>
std::expected<void, std::string>
checkBatchSingleSign(STObject const& batchSigner) const;
Expected<void, std::string>
std::expected<void, std::string>
checkBatchMultiSign(STObject const& batchSigner, Rules const& rules) const;
STBase*

View File

@@ -17,8 +17,8 @@ public:
STVector256() = default;
explicit STVector256(SField const& n);
explicit STVector256(std::vector<uint256> const& vector);
STVector256(SField const& n, std::vector<uint256> const& vector);
explicit STVector256(std::vector<uint256> vector);
STVector256(SField const& n, std::vector<uint256> vector);
STVector256(SerialIter& sit, SField const& name);
[[nodiscard]] SerializedTypeID
@@ -103,12 +103,12 @@ inline STVector256::STVector256(SField const& n) : STBase(n)
{
}
inline STVector256::STVector256(std::vector<uint256> const& vector) : value_(vector)
inline STVector256::STVector256(std::vector<uint256> vector) : value_(std::move(vector))
{
}
inline STVector256::STVector256(SField const& n, std::vector<uint256> const& vector)
: STBase(n), value_(vector)
inline STVector256::STVector256(SField const& n, std::vector<uint256> vector)
: STBase(n), value_(std::move(vector))
{
}

View File

@@ -1,7 +1,6 @@
#pragma once
#include <xrpl/basics/Buffer.h>
#include <xrpl/basics/Expected.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Issue.h>
#include <xrpl/protocol/PublicKey.h>
@@ -15,6 +14,7 @@
#include <boost/container/vector.hpp>
#include <cstddef>
#include <expected>
#include <utility>
#include <vector>

View File

@@ -37,7 +37,7 @@ private:
// The largest "small object" we can accommodate
static constexpr std::size_t kMaxSize = 72;
std::aligned_storage<kMaxSize>::type d_ = {};
alignas(std::max_align_t) std::byte d_[kMaxSize] = {};
STBase* p_ = nullptr;
public:

View File

@@ -15,6 +15,7 @@
// Add new amendments to the top of this list.
// Keep it sorted in reverse chronological order.
XRPL_FIX (Cleanup3_3_0, Supported::Yes, VoteBehavior::DefaultNo)
XRPL_FIX (Cleanup3_2_0, Supported::Yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(MPTokensV2, Supported::No, VoteBehavior::DefaultNo)
XRPL_FIX (Cleanup3_1_3, Supported::Yes, VoteBehavior::DefaultYes)
@@ -64,7 +65,6 @@ XRPL_FIX (DisallowIncomingV1, Supported::Yes, VoteBehavior::DefaultNo
XRPL_FEATURE(XChainBridge, Supported::Yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(AMM, Supported::Yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(Clawback, Supported::Yes, VoteBehavior::DefaultNo)
XRPL_FIX (UniversalNumber, Supported::Yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(XRPFees, Supported::Yes, VoteBehavior::DefaultNo)
XRPL_FIX (RemoveNFTokenAutoTrustLine, Supported::Yes, VoteBehavior::DefaultYes)
@@ -112,6 +112,7 @@ XRPL_RETIRE_FIX(RmSmallIncreasedQOffers)
XRPL_RETIRE_FIX(STAmountCanonicalize)
XRPL_RETIRE_FIX(TakerDryOfferRemoval)
XRPL_RETIRE_FIX(TrustLinesToSelf)
XRPL_RETIRE_FIX(UniversalNumber)
XRPL_RETIRE_FEATURE(Checks)
XRPL_RETIRE_FEATURE(CheckCashMakesTrustLine)

View File

@@ -1,10 +1,10 @@
#pragma once
#include <xrpl/basics/Expected.h>
#include <xrpl/basics/contract.h>
#include <xrpl/protocol/detail/token_errors.h>
#include <cstdint>
#include <expected>
#include <optional>
#include <span>
#include <string>
@@ -13,7 +13,7 @@
namespace xrpl {
template <class T>
using B58Result = Expected<T, std::error_code>;
using B58Result = std::expected<T, std::error_code>;
enum class TokenType : std::uint8_t {
None = 1, // unused

View File

@@ -1,6 +1,5 @@
#pragma once
#include <xrpl/basics/BasicConfig.h>
#include <xrpl/beast/net/IPEndpoint.h>
#include <boost/asio/ip/address.hpp>
@@ -14,6 +13,7 @@
#include <optional>
#include <set>
#include <string>
#include <vector>
namespace boost::asio::ssl {
class context; // NOLINT(readability-identifier-naming) -- external library name
@@ -21,6 +21,8 @@ class context; // NOLINT(readability-identifier-naming) -- external library nam
namespace xrpl {
class Section;
/** Configuration information for a Server listening port. */
struct Port
{

View File

@@ -10,6 +10,7 @@
#include <functional>
#include <memory>
#include <ostream>
#include <string_view>
#include <vector>
namespace xrpl {
@@ -53,10 +54,10 @@ public:
/** Send a copy of data asynchronously. */
/** @{ */
void
write(std::string const& s)
write(std::string_view s)
{
if (!s.empty())
write(&s[0], std::distance(s.begin(), s.end()));
write(s.data(), s.size());
}
template <typename BufferSequence>

View File

@@ -161,7 +161,7 @@ public:
setLedgerSeq(std::uint32_t lseq);
bool
fetchRoot(SHAMapHash const& hash, SHAMapSyncFilter* filter);
fetchRoot(SHAMapHash const& hash, SHAMapSyncFilter const* filter);
// normal hash access functions
@@ -248,7 +248,7 @@ public:
@param return The nodes known to be missing
*/
std::vector<std::pair<SHAMapNodeID, uint256>>
getMissingNodes(int maxNodes, SHAMapSyncFilter* filter);
getMissingNodes(int maxNodes, SHAMapSyncFilter const* filter);
bool
getNodeFat(
@@ -281,9 +281,9 @@ public:
serializeRoot(Serializer& s) const;
SHAMapAddNode
addRootNode(SHAMapHash const& hash, Slice const& rootNode, SHAMapSyncFilter* filter);
addRootNode(SHAMapHash const& hash, Slice const& rootNode, SHAMapSyncFilter const* filter);
SHAMapAddNode
addKnownNode(SHAMapNodeID const& nodeID, Slice const& rawNode, SHAMapSyncFilter* filter);
addKnownNode(SHAMapNodeID const& nodeID, Slice const& rawNode, SHAMapSyncFilter const* filter);
// status functions
void
@@ -343,11 +343,11 @@ private:
SHAMapTreeNodePtr
fetchNodeNT(SHAMapHash const& hash) const;
SHAMapTreeNodePtr
fetchNodeNT(SHAMapHash const& hash, SHAMapSyncFilter* filter) const;
fetchNodeNT(SHAMapHash const& hash, SHAMapSyncFilter const* filter) const;
SHAMapTreeNodePtr
fetchNode(SHAMapHash const& hash) const;
SHAMapTreeNodePtr
checkFilter(SHAMapHash const& hash, SHAMapSyncFilter* filter) const;
checkFilter(SHAMapHash const& hash, SHAMapSyncFilter const* filter) const;
/** Update hashes up to the root */
void
@@ -411,7 +411,7 @@ private:
descendAsync(
SHAMapInnerNode* parent,
int branch,
SHAMapSyncFilter* filter,
SHAMapSyncFilter const* filter,
bool& pending,
descendCallback&&) const;
@@ -420,7 +420,7 @@ private:
SHAMapInnerNode* parent,
SHAMapNodeID const& parentID,
int branch,
SHAMapSyncFilter* filter) const;
SHAMapSyncFilter const* filter) const;
// Non-storing
// Does not hook the returned node to its parent
@@ -461,7 +461,7 @@ private:
// basic parameters
int max;
SHAMapSyncFilter* filter;
SHAMapSyncFilter const* filter;
int const maxDefer;
std::uint32_t generation;
@@ -500,7 +500,11 @@ private:
// reads
std::map<SHAMapInnerNode*, SHAMapNodeID> resumes;
MissingNodes(int max, SHAMapSyncFilter* filter, int maxDefer, std::uint32_t generation)
MissingNodes(
int max,
SHAMapSyncFilter const* filter,
int maxDefer,
std::uint32_t generation)
: max(max), filter(filter), maxDefer(maxDefer), generation(generation), deferred(0)
{
missingNodes.reserve(max);

View File

@@ -5,6 +5,7 @@
#include <optional>
#include <string>
#include <string_view>
#include <tuple>
namespace xrpl {
@@ -127,7 +128,7 @@ operator<<(std::ostream& out, SHAMapNodeID const& node)
deserializeSHAMapNodeID(void const* data, std::size_t size);
[[nodiscard]] inline std::optional<SHAMapNodeID>
deserializeSHAMapNodeID(std::string const& s)
deserializeSHAMapNodeID(std::string_view s)
{
return deserializeSHAMapNodeID(s.data(), s.size());
}

View File

@@ -1,11 +1,11 @@
#pragma once
#include <xrpl/basics/Expected.h> //
#include <xrpl/beast/utility/Journal.h> // beast::Journal
#include <xrpl/protocol/TER.h> // temMALFORMED
#include <xrpl/protocol/UintTypes.h> // AccountID
#include <xrpl/tx/Transactor.h> // NotTEC
#include <expected>
#include <optional>
#include <string_view>
@@ -60,7 +60,7 @@ public:
// obj Contains a SignerEntries field that is an STArray.
// journal For reporting error conditions.
// annotation Source of SignerEntries, like "ledger" or "transaction".
static Expected<std::vector<SignerEntry>, NotTEC>
static std::expected<std::vector<SignerEntry>, NotTEC>
deserialize(STObject const& obj, beast::Journal journal, std::string_view annotation);
};

View File

@@ -1,9 +1,10 @@
#pragma once
#include <xrpl/basics/Expected.h>
#include <xrpl/protocol/UintTypes.h>
#include <xrpl/tx/Transactor.h>
#include <expected>
namespace xrpl {
// NOLINTBEGIN(readability-redundant-member-init)
@@ -61,7 +62,7 @@ public:
ReadView const& view,
beast::Journal const& j) override;
static Expected<MPTID, TER>
static std::expected<MPTID, TER>
create(ApplyView& view, beast::Journal journal, MPTCreateArgs const& args);
};

View File

@@ -2,6 +2,8 @@
#include <xrpl/tx/Transactor.h>
#include <expected>
namespace xrpl {
class VaultClawback : public Transactor
@@ -34,7 +36,7 @@ public:
beast::Journal const& j) override;
private:
Expected<std::pair<STAmount, STAmount>, TER>
std::expected<std::pair<STAmount, STAmount>, TER>
assetsToClawback(
SLE::ref vault,
SLE::const_ref sleShareIssuance,

View File

@@ -71,7 +71,7 @@ if [ ! -e "${target}" ]; then
fi
EOF
COPY nix/docker/check-tools.sh /tmp/check-tools.sh
COPY bin/check-tools.sh /tmp/check-tools.sh
RUN /tmp/check-tools.sh
# Sanity-check that the g++/clang++ are able to build binaries, including sanitizer-instrumented ones.
@@ -93,7 +93,7 @@ RUN if echo "${BASE_IMAGE}" | grep -qiE 'nixos'; then \
SHELL ["/bin/bash", "-e", "-o", "pipefail", "-c"]
# Sanity-check that the built binaries run correctly in the vanilla base image, with the necessary sanitizer runtime libraries installed.
COPY nix/docker/install-sanitizer-libs.sh /tmp/install-sanitizer-libs.sh
COPY bin/install-sanitizer-libs.sh /tmp/install-sanitizer-libs.sh
COPY nix/docker/test_files/run-test-binaries.sh /tmp/run-test-binaries.sh
COPY --from=final /tmp/bins /tmp/bins

90
nix/docker/README.md Normal file
View File

@@ -0,0 +1,90 @@
# Nix CI Docker images
This directory builds the Docker images used by xrpld's Linux CI. Each image
bundles the **exact same toolchain that the Nix development shell provides**
(see [`docs/build/nix.md`](../../docs/build/nix.md)), so what runs in CI matches
what developers get locally from `nix develop`.
The toolchain (CMake, Ninja, Conan, GCC, Clang, clang-tidy, the
sanitizer/coverage tools, …) is defined in [`nix/packages.nix`](../packages.nix)
and assembled for CI by [`nix/ci-env.nix`](../ci-env.nix). The Docker build
turns that Nix environment into an ordinary container image layered on top of a
conventional base image (Ubuntu, Debian, RHEL, or `nixos/nix`).
## Images
The images are built by the [`build-nix-images.yml`](../../.github/workflows/build-nix-images.yml)
workflow and pushed to `ghcr.io/xrplf/xrpld/nix-<distro>`. The `<distro>` is
selected through the `BASE_IMAGE` build argument; the base images are the
**oldest supported version** of each distribution we target:
| Image | `BASE_IMAGE` | Notes |
| ------------ | -------------------------------------------- | -------------------------------------------------- |
| `nix-nixos` | `nixos/nix:latest` | Build/lint only; binaries are not run (see below). |
| `nix-ubuntu` | `ubuntu:20.04` | Oldest supported Ubuntu (glibc 2.31). |
| `nix-debian` | `debian:bookworm` | |
| `nix-rhel` | `registry.access.redhat.com/ubi9/ubi:latest` | |
All images carry the full toolchain on `PATH` (via `/nix/ci-env/bin`) plus the
CA bundle shipped in the Nix environment, so HTTPS clients (git, curl, Conan)
work without `ca-certificates` being installed in the base image.
## Build stages
[`Dockerfile`](./Dockerfile) is a multi-stage build:
1. **`builder`** — On a `nixos/nix` builder, evaluate the flake and build the
CI environment (`nix/ci-env.nix`). The resulting Nix store closure (the
complete set of store paths the toolchain depends on) is copied into a
staging directory.
2. **`final`** — Start from `BASE_IMAGE`, copy in the Nix store closure and the
`ci-env` symlink tree, and wire up `PATH` and the CA bundle. It then:
- installs the dynamic linker if the base image lacks one (see
[How libc is handled](#how-libc-is-handled)),
- runs [`bin/check-tools.sh`](../../bin/check-tools.sh) to verify every
expected tool is present and runnable, and
- compiles the C++ test programs in
[`test_files/`](./test_files) with both `g++` and `clang++`, and sanitizers.
3. **`tester`** — Start again from a clean `BASE_IMAGE` (no Nix toolchain),
install only the sanitizer runtime libraries
([`install-sanitizer-libs.sh`](./install-sanitizer-libs.sh)), and run the
binaries compiled in `final`. This proves the binaries built with the Nix
toolchain actually run on a vanilla base image. On `nixos/nix` this step is
skipped (the binaries are patched for a conventional FHS loader).
4. **Output** — The final image is gated on the tester succeeding: it copies a
sentinel file out of `tester`, so a failed test run fails the whole build.
## How libc is handled
The goal is for binaries built in these images to run on the **oldest supported
base image** (Ubuntu 20.04, glibc 2.31) and newer — without the developer's Nix
toolchain being present at runtime. Two pieces make that work:
- **Compilers linked against an old glibc.** The Nix CI environment does not use
nixpkgs' current glibc. Instead it pins a 2020 nixpkgs snapshot whose primary
glibc is **2.31** (matching Ubuntu 20.04), via the `nixpkgs-custom-glibc`
flake input. GCC, Clang, binutils and compiler-rt are all rebuilt/wrapped
against this custom glibc (see [`nix/ci-env.nix`](../ci-env.nix)). As a result
the libraries they emit (`libstdc++`, `libgcc_s`, the sanitizer runtimes)
reference only symbols available in glibc 2.31.
- **An expected dynamic linker in the image.**
Binaries built in Nix environments reference a dynamic linker from Nix store paths, which won't be present in the base image. However,
[`loader-path.sh`](./loader-path.sh) reports the expected loader path for the
current architecture, so we can patch the binaries to use the correct loader.
The build then verifies all of this end to end: the test programs in
`test_files/` (a regular binary plus ASan/TSan/UBSan variants) are compiled in
`final`, their `PT_INTERP` is patched to the target loader, and they are run in
the clean `tester` stage to confirm each emits the expected sanitizer
diagnostic on a stock base image.
## Files
| File | Purpose |
| ----------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| [`./Dockerfile`](./Dockerfile) | Multi-stage build described above. |
| [`./loader-path.sh`](./loader-path.sh) | Print the dynamic-linker (`PT_INTERP`) path for the current architecture. |
| [`./test_files/`](./test_files) | C++ sources and scripts to compile and run the sanitizer smoke tests. |
| [`/bin/check-tools.sh`](../../bin/check-tools.sh) | Verify every expected tools are present and runnable. |
| [`/bin/install-sanitizer-libs.sh`](../../bin/install-sanitizer-libs.sh) | Install `libasan`/`libtsan`/`libubsan` runtimes on the supported base images. |

View File

@@ -1,35 +0,0 @@
#!/bin/bash
# Verify that every tool expected in the Nix CI env is present and runnable.
set -euo pipefail
ccache --version
clang --version
clang++ --version
clang-format --version
cmake --version
conan --version
curl --version
doxygen --version
g++ --version
gcc --version
gcov --version
gcovr --version
git --version
gpg --version
less --version
make --version
mold --version
netstat --version
ninja --version
perl --version
pkg-config --version
pre-commit --version
python3 --version
run-clang-tidy --help
vim --version
# A simple test to verify that git can clone a repository over HTTPS
# (i.e. the CA bundle is wired up). Clone to a temp dir and clean up.
tmp_clone="$(mktemp -d)"
git clone --depth 1 https://github.com/XRPLF/actions.git "${tmp_clone}/actions"
rm -rf "${tmp_clone}"

View File

@@ -9,12 +9,16 @@ in
{
commonPackages = with pkgs; [
ccache
clangbuildanalyzer
cmake
conan
curlMinimal # needed for codecov/codecov-action
doxygen
file # needed for cpack in Clio
gcovr
gh
git
git-cliff
gnumake
gnupg # needed for signing commits & codecov/codecov-action
llvmPackages_22.clang-tools

View File

@@ -1 +1 @@
halt_on_error=false
halt_on_error=true

View File

@@ -72,7 +72,7 @@ vptr:boost
# Google protobuf - intentional overflows in hash functions
undefined:protobuf
unsigned-integer-overflow:google/protobuf/stubs/stringpiece.h
unsigned-integer-overflow:protobuf
# gRPC intentional overflows in timer calculations
unsigned-integer-overflow:grpc
@@ -102,47 +102,103 @@ undefined:nudb
# Snappy compression library intentional overflows
unsigned-integer-overflow:snappy.cc
# Abseil intentional overflows
unsigned-integer-overflow:absl/strings/numbers.cc
unsigned-integer-overflow:absl/strings/internal/cord_rep_flat.h
unsigned-integer-overflow:absl/base/internal/low_level_alloc.cc
unsigned-integer-overflow:absl/hash/internal/hash.h
unsigned-integer-overflow:absl/container/internal/raw_hash_set.h
# Abseil intentional overflows in hashing, RNG and time arithmetic.
# Matched at library scope (like boost above): the wraparound is by design
# across many absl files (hash mixing, raw_hash_set probing, duration math,
# int128, uniform_int_distribution), so listing individual files just churns.
unsigned-integer-overflow:absl
# Standard library intentional overflows
unsigned-integer-overflow:basic_string.h
unsigned-integer-overflow:bits/align.h
unsigned-integer-overflow:bits/basic_string.tcc
unsigned-integer-overflow:bits/chrono.h
unsigned-integer-overflow:bits/random.h
unsigned-integer-overflow:bits/random.tcc
unsigned-integer-overflow:bits/stl_algobase.h
unsigned-integer-overflow:bits/string_view.tcc
unsigned-integer-overflow:bits/uniform_int_dist.h
unsigned-integer-overflow:string_view
unsigned-integer-overflow:__random/seed_seq.h
unsigned-integer-overflow:__charconv/traits.h
unsigned-integer-overflow:__chrono/duration.h
# libstdc++ <bit> (std::__bit_ceil etc.) negates an unsigned width; <bit> is a
# distinct header from the bits/ directory so it needs its own entry.
unsigned-integer-overflow:include/c++/*/bit
# =============================================================================
# Rippled code suppressions
# =============================================================================
# Signed integer negation (-value) in amount types.
# INT64_MIN cannot occur in practice due to domain invariants (mantissa ranges
# are well within int64_t bounds), but UBSan flags the pattern as potential
# signed overflow. Narrowed to operator- to avoid suppressing unrelated
# overflows anywhere in a stack trace containing these type names.
signed-integer-overflow:operator-*IOUAmount*
signed-integer-overflow:operator-*XRPAmount*
signed-integer-overflow:operator-*MPTAmount*
signed-integer-overflow:operator-*STAmount*
# These suppressions are keyed by SOURCE FILE, not function name. This UBSan
# build runs without symbol information, so the runtime only knows the
# file:line of each report, never the enclosing function — function-name
# patterns silently never match. Each entry below is therefore scoped to the
# file whose arithmetic is intentional; the comment names the specific
# construct.
# STAmount::operator+ signed addition — operands are bounded by total supply
# (~10^17 for XRP, ~10^18 for MPT) so overflow cannot occur in practice.
signed-integer-overflow:operator+*STAmount*
# STAmount amount-type arithmetic. Unary negation of the mantissa in xrp()/
# iou()/mpt()/canonicalize() and getInt64Value, plus bounded +/- on amounts:
# INT64_MIN cannot occur because canonicalize() keeps the mantissa well within
# int64_t, and operands are bounded by total supply (~10^17 XRP, ~10^18 MPT).
signed-integer-overflow:protocol/STAmount.cpp
# STAmount::getRate uses unsigned shift and addition
unsigned-integer-overflow:*STAmount*getRate*
# STAmount::serialize uses unsigned bitwise operations
unsigned-integer-overflow:*STAmount*serialize*
# nft::cipheredTaxon uses intentional uint32 wraparound (LCG permutation);
# the helper lives in the generated protocol header nft.h.
unsigned-integer-overflow:protocol/nft.h
# nft::cipheredTaxon uses intentional uint32 wraparound (LCG permutation)
unsigned-integer-overflow:cipheredTaxon
# STPathElement::getHash multiplies/adds accumulators (non-secure, speed-first).
unsigned-integer-overflow:protocol/STPathSet.cpp
# beast XorShiftEngine PRNG and murmurhash3 mixing wrap by design.
unsigned-integer-overflow:beast/xor_shift_engine.h
# Number::normalizeToRange multiplies the mantissa by powers of ten; the result
# is intentionally allowed to wrap while searching for the in-range value.
unsigned-integer-overflow:basics/Number.h
# Counter / sequence arithmetic with intentional unsigned wraparound, each
# guarded by an explicit overflow or domain check at the call site:
# base_uint operator++/-- wrap by definition;
# ApplyView::insertPage ++page is asserted to wrap to 0 (page exhaustion);
# confineOwnerCount documents "overflow is well defined on unsigned";
# NFTokenMint checks tokenSeq + 1u == 0u; AmendmentTable does (seq - 1) / 256.
unsigned-integer-overflow:basics/base_uint.h
unsigned-integer-overflow:ledger/ApplyView.cpp
unsigned-integer-overflow:ledger/helpers/AccountRootHelpers.cpp
unsigned-integer-overflow:tx/transactors/nft/NFTokenMint.cpp
unsigned-integer-overflow:app/misc/detail/AmendmentTable.cpp
# Sentinel / bounded subtractions that wrap by design (loop counters, reverse
# iteration, "not found" sentinels, balance math bounded by issuance invariants,
# base58/base64 codec index math, hash-router and role bit math).
unsigned-integer-overflow:shamap/SHAMap.cpp
unsigned-integer-overflow:protocol/Permissions.cpp
unsigned-integer-overflow:protocol/tokens.cpp
unsigned-integer-overflow:basics/base64.cpp
unsigned-integer-overflow:json/json_value.cpp
unsigned-integer-overflow:app/misc/NetworkOPs.cpp
unsigned-integer-overflow:rpc/detail/Role.cpp
unsigned-integer-overflow:tx/transactors/oracle/OracleSet.cpp
unsigned-integer-overflow:ledger/helpers/MPTokenHelpers.cpp
unsigned-integer-overflow:crypto/RFC1751.cpp
unsigned-integer-overflow:tx/paths/detail/StrandFlow.h
unsigned-integer-overflow:protocol/STObject.h
# GetAggregatePrice negates an unsigned trim count to step a reverse iterator;
# trimCount is bounded by the price set size.
unsigned-integer-overflow:rpc/handlers/orderbook/GetAggregatePrice.cpp
# Test-only intentional overflow/underflow in fixture and unit-test arithmetic.
unsigned-integer-overflow:tests/libxrpl/basics/RangeSet.cpp
unsigned-integer-overflow:test/app/Batch_test.cpp
unsigned-integer-overflow:test/app/Invariants_test.cpp
unsigned-integer-overflow:test/app/Loan_test.cpp
unsigned-integer-overflow:test/app/NFToken_test.cpp
unsigned-integer-overflow:test/app/OfferMPT_test.cpp
unsigned-integer-overflow:test/app/Offer_test.cpp
unsigned-integer-overflow:test/app/Path_test.cpp
unsigned-integer-overflow:test/jtx/impl/acctdelete.cpp
unsigned-integer-overflow:test/ledger/SkipList_test.cpp
unsigned-integer-overflow:test/rpc/Subscribe_test.cpp
signed-integer-overflow:test/basics/XRPAmount_test.cpp

View File

@@ -66,7 +66,7 @@ public:
class StatsDHookImpl : public HookImpl, public StatsDMetricBase
{
public:
StatsDHookImpl(HandlerType handler, std::shared_ptr<StatsDCollectorImp> const& impl);
StatsDHookImpl(HandlerType handler, std::shared_ptr<StatsDCollectorImp> impl);
~StatsDHookImpl() override;
@@ -86,7 +86,7 @@ private:
class StatsDCounterImpl : public CounterImpl, public StatsDMetricBase
{
public:
StatsDCounterImpl(std::string name, std::shared_ptr<StatsDCollectorImp> const& impl);
StatsDCounterImpl(std::string name, std::shared_ptr<StatsDCollectorImp> impl);
~StatsDCounterImpl() override;
@@ -115,7 +115,7 @@ private:
class StatsDEventImpl : public EventImpl
{
public:
StatsDEventImpl(std::string name, std::shared_ptr<StatsDCollectorImp> const& impl);
StatsDEventImpl(std::string name, std::shared_ptr<StatsDCollectorImp> impl);
~StatsDEventImpl() override = default;
@@ -140,7 +140,7 @@ private:
class StatsDGaugeImpl : public GaugeImpl, public StatsDMetricBase
{
public:
StatsDGaugeImpl(std::string name, std::shared_ptr<StatsDCollectorImp> const& impl);
StatsDGaugeImpl(std::string name, std::shared_ptr<StatsDCollectorImp> impl);
~StatsDGaugeImpl() override;
@@ -174,7 +174,7 @@ private:
class StatsDMeterImpl : public MeterImpl, public StatsDMetricBase
{
public:
explicit StatsDMeterImpl(std::string name, std::shared_ptr<StatsDCollectorImp> const& impl);
explicit StatsDMeterImpl(std::string name, std::shared_ptr<StatsDCollectorImp> impl);
~StatsDMeterImpl() override;
@@ -478,8 +478,8 @@ public:
//------------------------------------------------------------------------------
StatsDHookImpl::StatsDHookImpl(HandlerType handler, std::shared_ptr<StatsDCollectorImp> const& impl)
: impl_(impl), handler_(std::move(handler))
StatsDHookImpl::StatsDHookImpl(HandlerType handler, std::shared_ptr<StatsDCollectorImp> impl)
: impl_(std::move(impl)), handler_(std::move(handler))
{
impl_->add(*this);
}
@@ -497,10 +497,8 @@ StatsDHookImpl::doProcess()
//------------------------------------------------------------------------------
StatsDCounterImpl::StatsDCounterImpl(
std::string name,
std::shared_ptr<StatsDCollectorImp> const& impl)
: impl_(impl), name_(std::move(name))
StatsDCounterImpl::StatsDCounterImpl(std::string name, std::shared_ptr<StatsDCollectorImp> impl)
: impl_(std::move(impl)), name_(std::move(name))
{
impl_->add(*this);
}
@@ -550,8 +548,8 @@ StatsDCounterImpl::doProcess()
//------------------------------------------------------------------------------
StatsDEventImpl::StatsDEventImpl(std::string name, std::shared_ptr<StatsDCollectorImp> const& impl)
: impl_(impl), name_(std::move(name))
StatsDEventImpl::StatsDEventImpl(std::string name, std::shared_ptr<StatsDCollectorImp> impl)
: impl_(std::move(impl)), name_(std::move(name))
{
}
@@ -577,8 +575,8 @@ StatsDEventImpl::doNotify(EventImpl::value_type const& value)
//------------------------------------------------------------------------------
StatsDGaugeImpl::StatsDGaugeImpl(std::string name, std::shared_ptr<StatsDCollectorImp> const& impl)
: impl_(impl), name_(std::move(name))
StatsDGaugeImpl::StatsDGaugeImpl(std::string name, std::shared_ptr<StatsDCollectorImp> impl)
: impl_(std::move(impl)), name_(std::move(name))
{
impl_->add(*this);
}
@@ -664,8 +662,8 @@ StatsDGaugeImpl::doProcess()
//------------------------------------------------------------------------------
StatsDMeterImpl::StatsDMeterImpl(std::string name, std::shared_ptr<StatsDCollectorImp> const& impl)
: impl_(impl), name_(std::move(name))
StatsDMeterImpl::StatsDMeterImpl(std::string name, std::shared_ptr<StatsDCollectorImp> impl)
: impl_(std::move(impl)), name_(std::move(name))
{
impl_->add(*this);
}

View File

@@ -1,4 +1,4 @@
#include <xrpl/basics/BasicConfig.h>
#include <xrpl/config/BasicConfig.h>
#include <xrpl/basics/StringUtilities.h>

View File

@@ -13,6 +13,7 @@
#include <cstdint>
#include <cstring>
#include <string>
#include <string_view>
#include <vector>
namespace xrpl {
@@ -306,7 +307,7 @@ RFC1751::standard(std::string& strWord)
// Binary search of dictionary.
int
RFC1751::wsrch(std::string const& strWord, int iMin, int iMax)
RFC1751::wsrch(std::string_view strWord, int iMin, int iMax)
{
int iResult = -1;

View File

@@ -40,14 +40,10 @@ CanonicalTXSet::accountKey(AccountID const& account)
}
void
CanonicalTXSet::insert(std::shared_ptr<STTx const> const& txn)
CanonicalTXSet::insert(std::shared_ptr<STTx const> txn)
{
map_.insert(
std::make_pair(
Key(accountKey(txn->getAccountID(sfAccount)),
txn->getSeqProxy(),
txn->getTransactionID()),
txn));
Key key(accountKey(txn->getAccountID(sfAccount)), txn->getSeqProxy(), txn->getTransactionID());
map_.emplace(key, std::move(txn));
}
std::shared_ptr<STTx const>

View File

@@ -1,6 +1,5 @@
#include <xrpl/ledger/helpers/AMMHelpers.h>
#include <xrpl/basics/Expected.h>
#include <xrpl/basics/Log.h>
#include <xrpl/basics/Number.h>
#include <xrpl/basics/base_uint.h>
@@ -34,6 +33,7 @@
#include <algorithm>
#include <chrono>
#include <cstdint>
#include <expected>
#include <functional>
#include <optional>
#include <tuple>
@@ -433,7 +433,7 @@ ammPoolHolds(
return std::make_pair(assetInBalance, assetOutBalance);
}
Expected<std::tuple<STAmount, STAmount, STAmount>, TER>
std::expected<std::tuple<STAmount, STAmount, STAmount>, TER>
ammHolds(
ReadView const& view,
SLE const& ammSle,
@@ -489,7 +489,7 @@ ammHolds(
return std::make_optional(std::make_pair(asset1, asset2));
}();
if (!assets)
return Unexpected(tecAMM_INVALID_TOKENS);
return std::unexpected(tecAMM_INVALID_TOKENS);
auto const [amount1, amount2] = ammPoolHolds(
view,
ammSle.getAccountID(sfAccount),
@@ -821,7 +821,7 @@ initializeFeeAuctionVote(
auctionSlot.makeFieldAbsent(sfAuthAccounts);
}
Expected<bool, TER>
std::expected<bool, TER>
isOnlyLiquidityProvider(ReadView const& view, Issue const& ammIssue, AccountID const& lpAccount)
{
// Liquidity Provider (LP) must have one LPToken trustline
@@ -852,18 +852,18 @@ isOnlyLiquidityProvider(ReadView const& view, Issue const& ammIssue, AccountID c
{
auto const ownerDir = view.read(currentIndex);
if (!ownerDir)
return Unexpected<TER>(tecINTERNAL); // LCOV_EXCL_LINE
return std::unexpected<TER>(tecINTERNAL); // LCOV_EXCL_LINE
for (auto const& key : ownerDir->getFieldV256(sfIndexes))
{
auto const sle = view.read(keylet::child(key));
if (!sle)
return Unexpected<TER>(tecINTERNAL); // LCOV_EXCL_LINE
return std::unexpected<TER>(tecINTERNAL); // LCOV_EXCL_LINE
auto const entryType = sle->getFieldU16(sfLedgerEntryType);
// Only one AMM object
if (entryType == ltAMM)
{
if (hasAMM)
return Unexpected<TER>(tecINTERNAL); // LCOV_EXCL_LINE
return std::unexpected<TER>(tecINTERNAL); // LCOV_EXCL_LINE
hasAMM = true;
continue;
}
@@ -873,7 +873,7 @@ isOnlyLiquidityProvider(ReadView const& view, Issue const& ammIssue, AccountID c
continue;
}
if (entryType != ltRIPPLE_STATE)
return Unexpected<TER>(tecINTERNAL); // LCOV_EXCL_LINE
return std::unexpected<TER>(tecINTERNAL); // LCOV_EXCL_LINE
auto const lowLimit = sle->getFieldAmount(sfLowLimit);
auto const highLimit = sle->getFieldAmount(sfHighLimit);
auto const isLPTrustline =
@@ -889,12 +889,12 @@ isOnlyLiquidityProvider(ReadView const& view, Issue const& ammIssue, AccountID c
{
// LP has exactly one LPToken trustline
if (++nLPTokenTrustLines > 1)
return Unexpected<TER>(tecINTERNAL); // LCOV_EXCL_LINE
return std::unexpected<TER>(tecINTERNAL); // LCOV_EXCL_LINE
}
// AMM account has at most two IOU trustlines
else if (++nIOUTrustLines > 2)
{
return Unexpected<TER>(tecINTERNAL); // LCOV_EXCL_LINE
return std::unexpected<TER>(tecINTERNAL); // LCOV_EXCL_LINE
}
}
// Another Liquidity Provider LPToken trustline
@@ -905,7 +905,7 @@ isOnlyLiquidityProvider(ReadView const& view, Issue const& ammIssue, AccountID c
// AMM account has at most two IOU trustlines
else if (++nIOUTrustLines > 2)
{
return Unexpected<TER>(tecINTERNAL); // LCOV_EXCL_LINE
return std::unexpected<TER>(tecINTERNAL); // LCOV_EXCL_LINE
}
}
auto const uNodeNext = ownerDir->getFieldU64(sfIndexNext);
@@ -913,15 +913,15 @@ isOnlyLiquidityProvider(ReadView const& view, Issue const& ammIssue, AccountID c
{
if (nLPTokenTrustLines != 1 || (nIOUTrustLines == 0 && nMPT == 0) ||
(nIOUTrustLines > 2 || nMPT > 2) || (nIOUTrustLines + nMPT) > 2)
return Unexpected<TER>(tecINTERNAL); // LCOV_EXCL_LINE
return std::unexpected<TER>(tecINTERNAL); // LCOV_EXCL_LINE
return true;
}
currentIndex = keylet::page(root, uNodeNext);
}
return Unexpected<TER>(tecINTERNAL); // LCOV_EXCL_LINE
return std::unexpected<TER>(tecINTERNAL); // LCOV_EXCL_LINE
}
Expected<bool, TER>
std::expected<bool, TER>
verifyAndAdjustLPTokenBalance(
Sandbox& sb,
STAmount const& lpTokens,
@@ -931,7 +931,7 @@ verifyAndAdjustLPTokenBalance(
auto const res = isOnlyLiquidityProvider(sb, lpTokens.get<Issue>(), account);
if (!res.has_value())
{
return Unexpected<TER>(res.error());
return std::unexpected<TER>(res.error());
}
if (res.value())
@@ -944,7 +944,7 @@ verifyAndAdjustLPTokenBalance(
}
else
{
return Unexpected<TER>(tecAMM_INVALID_TOKENS);
return std::unexpected<TER>(tecAMM_INVALID_TOKENS);
}
}
return true;

View File

@@ -1,6 +1,5 @@
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/basics/Expected.h>
#include <xrpl/basics/Log.h>
#include <xrpl/basics/base_uint.h>
#include <xrpl/basics/contract.h>
@@ -22,6 +21,7 @@
#include <algorithm>
#include <cstdint>
#include <expected>
#include <limits>
#include <memory>
#include <optional>
@@ -202,7 +202,7 @@ isPseudoAccount(SLE::const_pointer sleAcct, std::set<SField const*> const& pseud
}) > 0;
}
Expected<SLE::pointer, TER>
std::expected<SLE::pointer, TER>
createPseudoAccount(ApplyView& view, uint256 const& pseudoOwnerKey, SField const& ownerField)
{
[[maybe_unused]]
@@ -216,7 +216,7 @@ createPseudoAccount(ApplyView& view, uint256 const& pseudoOwnerKey, SField const
auto const accountId = pseudoAccountAddress(view, pseudoOwnerKey);
if (accountId == beast::kZero)
return Unexpected(tecDUPLICATE);
return std::unexpected(tecDUPLICATE);
// Create pseudo-account.
auto account = std::make_shared<SLE>(keylet::account(accountId));

View File

@@ -1,6 +1,5 @@
#include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/basics/Expected.h>
#include <xrpl/basics/Log.h>
#include <xrpl/basics/Slice.h>
#include <xrpl/basics/base_uint.h>
@@ -24,6 +23,7 @@
#include <xrpl/protocol/digest.h>
#include <cstdint>
#include <expected>
#include <limits>
#include <set>
#include <unordered_set>
@@ -43,7 +43,7 @@ checkExpired(SLE const& sleCredential, NetClock::time_point const& closed)
}
[[nodiscard]]
static Expected<bool, TER>
static std::expected<bool, TER>
removeExpired(ApplyView& view, STVector256 const& arr, beast::Journal const j)
{
auto const closeTime = view.header().parentCloseTime;
@@ -61,7 +61,7 @@ removeExpired(ApplyView& view, STVector256 const& arr, beast::Journal const j)
// delete expired credentials even if the transaction failed
auto const err = deleteSLE(view, sleCred, j);
if (view.rules().enabled(fixCleanup3_1_3) && !isTesSuccess(err))
return Unexpected(err);
return std::unexpected(err);
foundExpired = true;
}
}

View File

@@ -1,6 +1,5 @@
#include <xrpl/ledger/helpers/LendingHelpers.h>
#include <xrpl/basics/Expected.h>
#include <xrpl/basics/Log.h>
#include <xrpl/basics/Number.h>
#include <xrpl/basics/chrono.h>
@@ -25,6 +24,7 @@
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <expected>
#include <string_view>
#include <utility>
@@ -514,7 +514,7 @@ doPayment(
* The function preserves accumulated rounding errors across the re-amortization
* to ensure the loan state remains consistent with its payment history.
*/
Expected<std::pair<LoanPaymentParts, LoanProperties>, TER>
std::expected<std::pair<LoanPaymentParts, LoanProperties>, TER>
tryOverpayment(
Rules const& rules,
Asset const& asset,
@@ -643,7 +643,7 @@ tryOverpayment(
JLOG(j.warn()) << "Principal overpayment would cause the loan to be in "
"an invalid state. Ignore the overpayment";
return Unexpected(tesSUCCESS);
return std::unexpected(tesSUCCESS);
}
// Validate that all computed properties are reasonable. These checks should
@@ -660,7 +660,7 @@ tryOverpayment(
<< ", PeriodicPayment : " << newLoanProperties.periodicPayment
<< ", ManagementFeeOwedToBroker: "
<< newLoanProperties.loanState.managementFeeDue;
return Unexpected(tesSUCCESS);
return std::unexpected(tesSUCCESS);
// LCOV_EXCL_STOP
}
@@ -685,7 +685,7 @@ tryOverpayment(
{
JLOG(j.warn()) << "Principal overpayment would increase the value of "
"the loan. Ignore the overpayment";
return Unexpected(tesSUCCESS);
return std::unexpected(tesSUCCESS);
}
return std::make_pair(
@@ -718,7 +718,7 @@ tryOverpayment(
* gracefully without corrupting the ledger data.
*/
template <class NumberProxy>
Expected<LoanPaymentParts, TER>
std::expected<LoanPaymentParts, TER>
doOverpayment(
Rules const& rules,
Asset const& asset,
@@ -760,7 +760,7 @@ doOverpayment(
managementFeeRate,
j);
if (!ret)
return Unexpected(ret.error());
return std::unexpected(ret.error());
auto const& [loanPaymentParts, newLoanProperties] = *ret;
auto const newRoundedLoanState = newLoanProperties.loanState;
@@ -774,7 +774,7 @@ doOverpayment(
JLOG(j.warn()) << "Overpayment not allowed: principal "
<< "outstanding did not decrease. Before: " << *principalOutstandingProxy
<< ". After: " << newRoundedLoanState.principalOutstanding;
return Unexpected(tesSUCCESS);
return std::unexpected(tesSUCCESS);
// LCOV_EXCL_STOP
}
@@ -798,44 +798,44 @@ doOverpayment(
// (P * factor) / factor round-trip can leave the new principal one
// scale-unit high, so these equalities do not hold on the pre-amendment
// code path and must be gated to match the fix they verify.
if (rules.enabled(fixCleanup3_2_0))
{
// The valueChange returned by tryOverpayment satisfies
// valueChange = (newInterestDue - oldInterestDue) + untrackedInterest.
// Using the loan-state identity v = p + i + m and the adjacent
// `principal change agrees` assertion (dp = oldP - newP), this
// rearranges into three independently-computable terms:
//
// 1. TVO change beyond what principal repayment alone explains:
// newTVO - (oldTVO - dp)
// 2. Management fee released by re-amortization (positive when
// mfee decreased; zero when managementFeeRate == 0):
// oldMfee - newMfee
// 3. The overpayment's penalty interest part (= untrackedInterest
// for the overpayment path; see computeOverpaymentComponents):
// trackedInterestPart()
[[maybe_unused]] Number const tvoChange = newRoundedLoanState.valueOutstanding -
(totalValueOutstandingProxy - overpaymentComponents.trackedPrincipalDelta);
[[maybe_unused]] Number const managementFeeReleased =
managementFeeOutstandingProxy - newRoundedLoanState.managementFeeDue;
[[maybe_unused]] Number const interestPart = overpaymentComponents.trackedInterestPart();
//
// The valueChange returned by tryOverpayment satisfies
// valueChange = (newInterestDue - oldInterestDue) + untrackedInterest.
// Using the loan-state identity v = p + i + m and the adjacent
// `principal change agrees` assertion (dp = oldP - newP), this
// rearranges into three independently-computable terms:
//
// 1. TVO change beyond what principal repayment alone explains:
// newTVO - (oldTVO - dp)
// 2. Management fee released by re-amortization (positive when
// mfee decreased; zero when managementFeeRate == 0):
// oldMfee - newMfee
// 3. The overpayment's penalty interest part (= untrackedInterest
// for the overpayment path; see computeOverpaymentComponents):
// trackedInterestPart()
[[maybe_unused]] bool const fix320Enabled = rules.enabled(fixCleanup3_2_0);
XRPL_ASSERT_IF(
fix320Enabled,
overpaymentComponents.trackedPrincipalDelta ==
principalOutstandingProxy - newRoundedLoanState.principalOutstanding,
"xrpl::detail::doOverpayment : principal change agrees");
XRPL_ASSERT_PARTS(
overpaymentComponents.trackedPrincipalDelta ==
principalOutstandingProxy - newRoundedLoanState.principalOutstanding,
"xrpl::detail::doOverpayment",
"principal change agrees");
XRPL_ASSERT_IF(
fix320Enabled,
[&] {
Number const tvoChange = newRoundedLoanState.valueOutstanding -
(totalValueOutstandingProxy - overpaymentComponents.trackedPrincipalDelta);
Number const managementFeeReleased =
managementFeeOutstandingProxy - newRoundedLoanState.managementFeeDue;
Number const interestPart = overpaymentComponents.trackedInterestPart();
return loanPaymentParts.valueChange == tvoChange + managementFeeReleased + interestPart;
}(),
"xrpl::detail::doOverpayment : interest paid agrees");
XRPL_ASSERT_PARTS(
loanPaymentParts.valueChange == tvoChange + managementFeeReleased + interestPart,
"xrpl::detail::doOverpayment",
"interest paid agrees");
XRPL_ASSERT_PARTS(
overpaymentComponents.trackedPrincipalDelta == loanPaymentParts.principalPaid,
"xrpl::detail::doOverpayment",
"principal payment matches");
}
XRPL_ASSERT_IF(
fix320Enabled,
overpaymentComponents.trackedPrincipalDelta == loanPaymentParts.principalPaid,
"xrpl::detail::doOverpayment : principal payment matches");
// All validations passed, so update the proxy objects (which will
// modify the actual Loan ledger object)
@@ -860,7 +860,7 @@ doOverpayment(
*
* Implements equation (15) from XLS-66 spec, Section A-2 Equation Glossary
*/
Expected<ExtendedPaymentComponents, TER>
std::expected<ExtendedPaymentComponents, TER>
computeLatePayment(
Asset const& asset,
ApplyView const& view,
@@ -877,7 +877,7 @@ computeLatePayment(
// Check if the due date has passed. If not, reject the payment as
// being too soon
if (!hasExpired(view, nextDueDate))
return Unexpected(tecTOO_SOON);
return std::unexpected(tecTOO_SOON);
// Calculate the penalty interest based on how long the payment is overdue.
auto const latePaymentInterest = loanLatePaymentInterest(
@@ -929,7 +929,7 @@ computeLatePayment(
{
JLOG(j.warn()) << "Late loan payment amount is insufficient. Due: " << late.totalDue
<< ", paid: " << amount;
return Unexpected(tecINSUFFICIENT_PAYMENT);
return std::unexpected(tecINSUFFICIENT_PAYMENT);
}
return late;
@@ -954,7 +954,7 @@ computeLatePayment(
*
* Implements equation (26) from XLS-66 spec, Section A-2 Equation Glossary
*/
Expected<ExtendedPaymentComponents, TER>
std::expected<ExtendedPaymentComponents, TER>
computeFullPayment(
Asset const& asset,
ApplyView& view,
@@ -979,7 +979,7 @@ computeFullPayment(
{
// If this is the last payment, it has to be a regular payment
JLOG(j.warn()) << "Last payment cannot be a full payment.";
return Unexpected(tecKILLED);
return std::unexpected(tecKILLED);
}
// Calculate the theoretical principal based on the payment schedule.
@@ -1059,7 +1059,7 @@ computeFullPayment(
{
// If the payment is less than the full payment amount, it's not
// sufficient to be a full payment.
return Unexpected(tecINSUFFICIENT_PAYMENT);
return std::unexpected(tecINSUFFICIENT_PAYMENT);
}
return full;
@@ -1326,13 +1326,11 @@ computeOverpaymentComponents(
TenthBips32 const overpaymentFeeRate,
TenthBips16 const managementFeeRate)
{
if (rules.enabled(fixCleanup3_2_0))
{
XRPL_ASSERT(
overpayment > 0 && isRounded(asset, overpayment, loanScale),
"xrpl::detail::computeOverpaymentComponents : valid overpayment "
"amount");
}
XRPL_ASSERT_IF(
rules.enabled(fixCleanup3_2_0),
overpayment > 0 && isRounded(asset, overpayment, loanScale),
"xrpl::detail::computeOverpaymentComponents : valid overpayment "
"amount");
// First, deduct the fixed overpayment fee from the total amount.
// This reduces the effective payment that will be applied to the loan.
@@ -1782,7 +1780,7 @@ computeLoanProperties(
* It is an implementation of the make_payment function from the XLS-66
* spec. Section 3.2.4.4
*/
Expected<LoanPaymentParts, TER>
std::expected<LoanPaymentParts, TER>
loanMakePayment(
Asset const& asset,
ApplyView& view,
@@ -1802,7 +1800,7 @@ loanMakePayment(
// Loan complete this is already checked in LoanPay::preclaim()
// LCOV_EXCL_START
JLOG(j.warn()) << "Loan is already paid off.";
return Unexpected(tecKILLED);
return std::unexpected(tecKILLED);
// LCOV_EXCL_STOP
}
@@ -1814,7 +1812,7 @@ loanMakePayment(
if (*nextDueDateProxy == 0)
{
JLOG(j.warn()) << "Loan next payment due date is not set.";
return Unexpected(tecINTERNAL);
return std::unexpected(tecINTERNAL);
}
std::int32_t const loanScale = loan->at(sfLoanScale);
@@ -1852,7 +1850,7 @@ loanMakePayment(
<< startDate << ", prev payment due date is " << prevPaymentDateProxy
<< ", next payment due date is " << nextDueDateProxy << ", ledger time is "
<< view.parentCloseTime().time_since_epoch().count();
return Unexpected(tecEXPIRED);
return std::unexpected(tecEXPIRED);
}
// -------------------------------------------------------------
@@ -1902,13 +1900,13 @@ loanMakePayment(
// error() will be the TER returned if a payment is not made. It
// will only evaluate to true if it's unsuccessful. Otherwise,
// tesSUCCESS means nothing was done, so continue.
return Unexpected(fullPaymentComponents.error());
return std::unexpected(fullPaymentComponents.error());
}
// LCOV_EXCL_START
UNREACHABLE("xrpl::loanMakePayment : invalid full payment result");
JLOG(j.error()) << "Full payment computation failed unexpectedly.";
return Unexpected(tecINTERNAL);
return std::unexpected(tecINTERNAL);
// LCOV_EXCL_STOP
}
@@ -1970,13 +1968,13 @@ loanMakePayment(
{
// error() will be the TER returned if a payment is not made. It
// will only evaluate to true if it's unsuccessful.
return Unexpected(latePaymentComponents.error());
return std::unexpected(latePaymentComponents.error());
}
// LCOV_EXCL_START
UNREACHABLE("xrpl::loanMakePayment : invalid late payment result");
JLOG(j.error()) << "Late payment computation failed unexpectedly.";
return Unexpected(tecINTERNAL);
return std::unexpected(tecINTERNAL);
// LCOV_EXCL_STOP
}
@@ -2043,7 +2041,7 @@ loanMakePayment(
{
JLOG(j.warn()) << "Regular loan payment amount is insufficient. Due: " << periodic.totalDue
<< ", paid: " << amount;
return Unexpected(tecINSUFFICIENT_PAYMENT);
return std::unexpected(tecINSUFFICIENT_PAYMENT);
}
XRPL_ASSERT_PARTS(
@@ -2129,7 +2127,7 @@ loanMakePayment(
// made. It will only evaluate to true if it's unsuccessful.
// Otherwise, tesSUCCESS means nothing was done, so
// continue.
return Unexpected(overResult.error());
return std::unexpected(overResult.error());
}
}
}

View File

@@ -736,10 +736,10 @@ unlockEscrowMPT(
STAmount const& grossAmount,
beast::Journal j)
{
if (!view.rules().enabled(fixTokenEscrowV1))
{
XRPL_ASSERT(netAmount == grossAmount, "xrpl::unlockEscrowMPT : netAmount == grossAmount");
}
XRPL_ASSERT_IF(
!view.rules().enabled(fixTokenEscrowV1),
netAmount == grossAmount,
"xrpl::unlockEscrowMPT : netAmount == grossAmount");
auto const& issuer = netAmount.getIssuer();
auto const& mptIssue = netAmount.get<MPTIssue>();

View File

@@ -64,7 +64,7 @@ public:
boost::asio::io_context& ioContext,
unsigned short const port,
std::size_t maxResponseSize,
beast::Journal& j)
beast::Journal const& j)
: socket_(
ioContext,
gHttpClientSslContext->context()) // NOLINT(bugprone-unchecked-optional-access)
@@ -552,7 +552,7 @@ HTTPClient::get(
std::function<
bool(boost::system::error_code const& ecResult, int iStatus, std::string const& strData)>
complete,
beast::Journal& j)
beast::Journal const& j)
{
auto client = std::make_shared<HTTPClientImp>(ioContext, port, responseMax, j);
client->get(bSSL, deqSites, strPath, timeout, complete);
@@ -570,7 +570,7 @@ HTTPClient::get(
std::function<
bool(boost::system::error_code const& ecResult, int iStatus, std::string const& strData)>
complete,
beast::Journal& j)
beast::Journal const& j)
{
std::deque<std::string> const deqSites(1, strSite);
@@ -590,7 +590,7 @@ HTTPClient::request(
std::function<
bool(boost::system::error_code const& ecResult, int iStatus, std::string const& strData)>
complete,
beast::Journal& j)
beast::Journal const& j)
{
std::deque<std::string> const deqSites(1, strSite);

View File

@@ -1,12 +1,13 @@
#include <xrpl/nodestore/Database.h>
#include <xrpl/basics/BasicConfig.h>
#include <xrpl/basics/Log.h>
#include <xrpl/basics/base_uint.h>
#include <xrpl/basics/contract.h>
#include <xrpl/beast/core/CurrentThreadName.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/config/BasicConfig.h>
#include <xrpl/config/Constants.h>
#include <xrpl/json/json_forwards.h>
#include <xrpl/json/json_value.h>
#include <xrpl/nodestore/Backend.h>
@@ -38,8 +39,8 @@ Database::Database(
beast::Journal journal)
: j_(journal)
, scheduler_(scheduler)
, earliestLedgerSeq_(get<std::uint32_t>(config, "earliest_seq", kXrpLedgerEarliestSeq))
, requestBundle_(get<int>(config, "rq_bundle", 4))
, earliestLedgerSeq_(get<std::uint32_t>(config, Keys::kEarliestSeq, kXrpLedgerEarliestSeq))
, requestBundle_(get<int>(config, Keys::kRqBundle, 4))
, readThreads_(std::max(1, readThreads))
{
XRPL_ASSERT(readThreads, "xrpl::NodeStore::Database::Database : nonzero threads input");

View File

@@ -1,11 +1,11 @@
#include <xrpl/nodestore/detail/DatabaseRotatingImp.h>
#include <xrpl/basics/BasicConfig.h>
#include <xrpl/basics/Blob.h>
#include <xrpl/basics/Log.h>
#include <xrpl/basics/base_uint.h>
#include <xrpl/basics/contract.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/config/BasicConfig.h>
#include <xrpl/nodestore/Backend.h>
#include <xrpl/nodestore/Database.h>
#include <xrpl/nodestore/DatabaseRotating.h>

View File

@@ -1,9 +1,10 @@
#include <xrpl/nodestore/detail/ManagerImp.h>
#include <xrpl/basics/BasicConfig.h>
#include <xrpl/basics/contract.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/config/BasicConfig.h>
#include <xrpl/config/Constants.h>
#include <xrpl/nodestore/Backend.h>
#include <xrpl/nodestore/Database.h>
#include <xrpl/nodestore/Manager.h>
@@ -66,7 +67,7 @@ ManagerImp::makeBackend(
Scheduler& scheduler,
beast::Journal journal)
{
std::string const type{get(parameters, "type")};
std::string const type{get(parameters, Keys::kType)};
if (type.empty())
missingBackend();

View File

@@ -1,8 +1,9 @@
#include <xrpl/basics/BasicConfig.h>
#include <xrpl/basics/base_uint.h>
#include <xrpl/basics/contract.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/config/BasicConfig.h>
#include <xrpl/config/Constants.h>
#include <xrpl/nodestore/Backend.h>
#include <xrpl/nodestore/Factory.h>
#include <xrpl/nodestore/Manager.h>
@@ -90,7 +91,7 @@ private:
public:
MemoryBackend(size_t keyBytes, Section const& keyValues, beast::Journal journal)
: name_(get(keyValues, "path")), journal_(journal)
: name_(get(keyValues, Keys::kPath)), journal_(journal)
{
boost::ignore_unused(journal_); // Keep unused journal_ just in case.
if (name_.empty())

View File

@@ -1,10 +1,11 @@
#include <xrpl/basics/BasicConfig.h>
#include <xrpl/basics/Log.h>
#include <xrpl/basics/base_uint.h>
#include <xrpl/basics/contract.h>
#include <xrpl/beast/core/LexicalCast.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/config/BasicConfig.h>
#include <xrpl/config/Constants.h>
#include <xrpl/nodestore/Backend.h>
#include <xrpl/nodestore/Factory.h>
#include <xrpl/nodestore/Manager.h>
@@ -72,7 +73,7 @@ public:
: j(journal)
, keyBytes(keyBytes)
, burstSize(burstSize)
, name(get(keyValues, "path"))
, name(get(keyValues, Keys::kPath))
, blockSize(parseBlockSize(name, keyValues, journal))
, deletePath(false)
, scheduler(scheduler)
@@ -91,7 +92,7 @@ public:
: j(journal)
, keyBytes(keyBytes)
, burstSize(burstSize)
, name(get(keyValues, "path"))
, name(get(keyValues, Keys::kPath))
, blockSize(parseBlockSize(name, keyValues, journal))
, db(context)
, deletePath(false)
@@ -359,7 +360,7 @@ private:
std::size_t const blockSize = defaultSize;
std::string blockSizeStr;
if (!getIfExists(keyValues, "nudb_block_size", blockSizeStr))
if (!getIfExists(keyValues, Keys::kNudbBlockSize, blockSizeStr))
{
return blockSize; // Early return with default
}

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