Compare commits

...

37 Commits

Author SHA1 Message Date
Denis Angell
9d74e0af3b feat: Add sponsor reap for abandoned under-reserved accounts 2026-08-05 17:05:46 -04:00
Gregory Tsipenyuk
8d7524f03b fix: Use consistent endianness serializing MPT STIssue sequence (#7429)
Co-authored-by: Ed Hennis <ed@ripple.com>
Co-authored-by: David Fuelling <sappenin@gmail.com>
2026-08-05 17:54:44 +00:00
Ayaz Salikhov
41d6bb5f73 build: Fix build on macOS 15 and Nix environment (#7953) 2026-08-04 23:27:23 +00:00
Ayaz Salikhov
a75488e5ff docs: Add a fix for command not found: nix on macOS (#7951) 2026-08-04 16:17:41 +00:00
Vito Tumas
c3ee602002 test: Split Loan_test.cpp into topical suites (#7864)
Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
2026-08-04 15:43:59 +00:00
Vito Tumas
e0de716ee6 fix: Watch nix/*.nix files for direnv cache invalidation (#7948) 2026-08-04 13:49:18 +00:00
Alex Kremer
06488c1318 chore: Rename CamelCase namespaces to snake_case (#7933)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-08-04 13:46:55 +00:00
Luc des Trois Maisons
b8451ffa32 fix: Add missing value_type to JSON iterators (#7907) 2026-08-03 21:17:23 +00:00
Timur Yalymov
765babb20d fix: Add VaultInvariant check that lossUnrealized is non-negative (#7863)
Co-authored-by: Vito Tumas <5780819+Tapanito@users.noreply.github.com>
2026-08-03 21:11:33 +00:00
Braedon Klock
97f35add2e fix: Add null check for account object reads (#7717)
Co-authored-by: Mayukha Vadari <mvadari@ripple.com>
2026-08-03 21:08:42 +00:00
Alex Kremer
ecdd457f35 chore: Gtest migration followups first pass (#7884) 2026-07-30 23:04:38 +00:00
Ayaz Salikhov
85e73cbd32 ci: Run coverage first in CI (#7917) 2026-07-30 19:28:31 +00:00
Bart
21cd615407 perf: Replace node ID by depth in TMLedgerNode (#6353)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
2026-07-30 15:02:05 +00:00
Olek
3c0659d26b test: Add confidential mpt bulletproof tests (#7816) 2026-07-30 12:18:33 +00:00
Copilot
532506541f fix: Apply asfDisallowIncomingTrustline blocker to OfferCreate (#6307)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Mayukha Vadari <mvadari@gmail.com>
Co-authored-by: Mayukha Vadari <mvadari@ripple.com>
2026-07-30 12:17:32 +00:00
Vito Tumas
8a5eded4f1 feat: Implement LoanBroker cash-basis accounting (#7817) 2026-07-30 11:55:39 +00:00
Alex Kremer
6ddad54985 chore: Move lexical cast tests to gtest (#7873) 2026-07-29 22:54:46 +00:00
Alex Kremer
86832edc70 chore: Move semantic version tests to gtest (#7872)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-27 18:48:53 +00:00
Ayaz Salikhov
ff7fff2cf2 style: Make clang-tidy format files using clang-format rules (#7880) 2026-07-27 18:39:53 +00:00
Mayukha Vadari
2db631c915 ci: Change server_definitions upload config name (#7878) 2026-07-27 17:42:07 +00:00
Alex Kremer
6c9c7f0555 chore: Trivial gtest migrations (#7865) 2026-07-27 16:34:53 +00:00
Ayaz Salikhov
9466ecb5c2 ci: Group github-actions dependabot updates (#7876) 2026-07-27 14:32:53 +00:00
Sergey Kuznetsov
e0aa50c4be ci: Update CI image and prepare-runner action (#7874) 2026-07-27 14:18:01 +00:00
Andrzej Budzanowski
29120dfcbd test: Migrate nodestore tests from Beast to GTest (#7292)
Co-authored-by: Marek Foss <marek.foss@neti-soft.com>
Co-authored-by: Alex Kremer <akremer@ripple.com>
2026-07-27 13:00:14 +00:00
Andrzej Budzanowski
20801d98ac test: Improve the server status test to not race and randomly fail (#7304)
Co-authored-by: Alex Kremer <akremer@ripple.com>
2026-07-27 11:58:15 +00:00
dependabot[bot]
b878818e80 ci: [DEPENDABOT] bump actions/checkout from 7.0.0 to 7.0.1 (#7871)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-27 09:55:01 +00:00
Sergey Kuznetsov
fecfc0cf3f chore: Fix clang version in devshell (#7860)
Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
2026-07-24 17:30:20 +00:00
Ayaz Salikhov
ea0a6904f0 chore: Verify tooling version for Nix-managed environments (#7862) 2026-07-24 15:52:45 +00:00
Ayaz Salikhov
29d74142ae build: Patсh binary in local Linux nix environment (#7859)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-24 14:59:24 +00:00
Kassaking7
9afa1cf4d1 fix: Update PermissionedDEX invariant domain tracking for valid offer replacement (#7387)
Co-authored-by: Bart <bthomee@users.noreply.github.com>
2026-07-23 21:40:21 +00:00
Ed Hennis
7908aec2ec feat: Check default fields are not default when serializing (#6267)
Co-authored-by: Vito <5780819+Tapanito@users.noreply.github.com>
Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
Co-authored-by: Bart <bthomee@users.noreply.github.com>
2026-07-23 21:39:11 +00:00
Marek Foss
4c0180b3db test: Migrate csf and xrpld-consensus Beast non-JTx tests to GTest (#7046)
Co-authored-by: Alex Kremer <akremer@ripple.com>
2026-07-23 21:38:21 +00:00
Marek Foss
4acccfeda8 test: Modularize Peerfinder component and migrate Peerfinder tests from Beast to GTest and GMock (#7054)
Co-authored-by: Alex Kremer <akremer@ripple.com>
2026-07-23 21:00:06 +00:00
Ed Hennis
b89d75a2d5 test: Add an RAII class to manage the env.parseFailureExpected flag (#7669) 2026-07-23 20:57:00 +00:00
Ayaz Salikhov
40cdf49d15 build: Use custom libc in a devshell by default (#7852) 2026-07-23 19:05:24 +00:00
Mayukha Vadari
38c54c3f36 feat: Add fixCleanup3_4_0 amendment (no functionality yet) (#7854) 2026-07-23 18:50:59 +00:00
Sergey Kuznetsov
95e1ffea6e ci: Add llvm-tools-preview to rust toolchain (#7853) 2026-07-23 16:49:44 +00:00
557 changed files with 25742 additions and 19950 deletions

View File

@@ -75,6 +75,8 @@ Checks: "-*,
# readability-static-accessed-through-instance, # this check is probably unnecessary. It makes the code less readable
# ---
FormatStyle: file
CheckOptions:
bugprone-unsafe-functions.ReportMoreUnsafeFunctions: true
bugprone-unused-return-value.CheckedReturnTypes: ::std::error_code;::std::error_condition;::std::errc
@@ -83,6 +85,8 @@ CheckOptions:
readability-braces-around-statements.ShortStatementLines: 2
readability-identifier-naming.MacroDefinitionCase: UPPER_CASE
readability-identifier-naming.NamespaceCase: lower_case
readability-identifier-naming.InlineNamespaceCase: lower_case
readability-identifier-naming.ClassCase: CamelCase
readability-identifier-naming.StructCase: CamelCase
readability-identifier-naming.UnionCase: CamelCase

View File

@@ -30,7 +30,9 @@ ignoreRegExpList:
- ABCDEFGHIJKLMNOPQRSTUVWXYZ
- ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
overrides:
- filename: "**/*_test.cpp" # all test files
- filename:
- "**/*_test.cpp" # legacy boost.test files
- "src/tests/**/*.cpp" # gtest test files
ignoreRegExpList:
- /"[^"]*"/g # double-quoted strings
- /'[^']*'/g # single-quoted strings
@@ -172,7 +174,6 @@ words:
- MPTAMM
- MPTDEX
- Merkle
- Metafuncton
- misprediction
- missingok
- mptbalance

2
.envrc
View File

@@ -1 +1,3 @@
watch_file nix/*.nix
use flake

View File

@@ -15,3 +15,7 @@ updates:
commit-message:
prefix: "ci: [DEPENDABOT] "
target-branch: develop
groups:
github-actions:
patterns:
- "*"

View File

@@ -40,18 +40,18 @@ listed later.
| 04 | xrpl/protocol |
| 05 | xrpl/core xrpl/resource xrpl/server |
| 06 | xrpl/ledger xrpl/nodestore xrpl/net |
| 07 | xrpl/shamap |
| 07 | xrpl/shamap xrpl/consensus |
## xrpld Modules (Application Implementation)
| Level / Tier | Module(s) |
| ------------ | -------------------------------- |
| 05 | xrpld/conditions xrpld/consensus |
| 06 | xrpld/core xrpld/peerfinder |
| 07 | xrpld/shamap xrpld/overlay |
| 08 | xrpld/app |
| 09 | xrpld/rpc |
| 10 | xrpld/perflog |
| Level / Tier | Module(s) |
| ------------ | --------------------------- |
| 05 | xrpld/conditions |
| 06 | xrpld/core xrpld/peerfinder |
| 07 | xrpld/shamap xrpld/overlay |
| 08 | xrpld/app |
| 09 | xrpld/rpc |
| 10 | xrpld/perflog |
## Test Modules

View File

@@ -1,9 +1,6 @@
Loop: xrpld.app xrpld.overlay
xrpld.app > xrpld.overlay
Loop: xrpld.app xrpld.peerfinder
xrpld.peerfinder ~= xrpld.app
Loop: xrpld.app xrpld.rpc
xrpld.rpc > xrpld.app

View File

@@ -6,6 +6,8 @@ libxrpl.conditions > xrpl.basics
libxrpl.conditions > xrpl.conditions
libxrpl.config > xrpl.basics
libxrpl.config > xrpl.config
libxrpl.consensus > xrpl.basics
libxrpl.consensus > xrpl.consensus
libxrpl.core > xrpl.basics
libxrpl.core > xrpl.core
libxrpl.core > xrpl.json
@@ -25,6 +27,9 @@ libxrpl.nodestore > xrpl.config
libxrpl.nodestore > xrpl.json
libxrpl.nodestore > xrpl.nodestore
libxrpl.nodestore > xrpl.protocol
libxrpl.peerfinder > xrpl.basics
libxrpl.peerfinder > xrpl.peerfinder
libxrpl.peerfinder > xrpl.protocol
libxrpl.protocol > xrpl.basics
libxrpl.protocol > xrpl.json
libxrpl.protocol > xrpl.protocol
@@ -60,9 +65,9 @@ test.app > test.jtx
test.app > test.unit_test
test.app > xrpl.basics
test.app > xrpl.config
test.app > xrpl.consensus
test.app > xrpl.core
test.app > xrpld.app
test.app > xrpld.consensus
test.app > xrpld.core
test.app > xrpld.overlay
test.app > xrpld.rpc
@@ -83,12 +88,9 @@ test.basics > xrpl.protocol
test.beast > xrpl.basics
test.conditions > xrpl.basics
test.conditions > xrpl.conditions
test.consensus > test.csf
test.consensus > test.jtx
test.consensus > test.unit_test
test.consensus > xrpl.basics
test.consensus > xrpld.app
test.consensus > xrpld.consensus
test.consensus > xrpl.ledger
test.consensus > xrpl.protocol
test.consensus > xrpl.shamap
@@ -103,10 +105,6 @@ test.core > xrpl.json
test.core > xrpl.protocol
test.core > xrpl.rdb
test.core > xrpl.server
test.csf > xrpl.basics
test.csf > xrpld.consensus
test.csf > xrpl.json
test.csf > xrpl.ledger
test.json > test.jtx
test.json > xrpl.json
test.jtx > test.unit_test
@@ -132,12 +130,9 @@ test.ledger > xrpl.json
test.ledger > xrpl.ledger
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
test.nodestore > xrpl.rdb
test.overlay > test.jtx
test.overlay > test.unit_test
@@ -146,19 +141,13 @@ test.overlay > xrpl.config
test.overlay > xrpld.app
test.overlay > xrpld.core
test.overlay > xrpld.overlay
test.overlay > xrpld.peerfinder
test.overlay > xrpl.json
test.overlay > xrpl.nodestore
test.overlay > xrpl.peerfinder
test.overlay > xrpl.protocol
test.overlay > xrpl.resource
test.overlay > xrpl.server
test.overlay > xrpl.shamap
test.peerfinder > test.beast
test.peerfinder > test.unit_test
test.peerfinder > xrpl.basics
test.peerfinder > xrpld.core
test.peerfinder > xrpld.peerfinder
test.peerfinder > xrpl.protocol
test.protocol > test.jtx
test.protocol > test.unit_test
test.protocol > xrpl.basics
@@ -192,11 +181,13 @@ test.unit_test > xrpl.basics
test.unit_test > xrpl.protocol
tests.libxrpl > xrpl.basics
tests.libxrpl > xrpl.config
tests.libxrpl > xrpl.consensus
tests.libxrpl > xrpl.core
tests.libxrpl > xrpl.json
tests.libxrpl > xrpl.ledger
tests.libxrpl > xrpl.net
tests.libxrpl > xrpl.nodestore
tests.libxrpl > xrpl.peerfinder
tests.libxrpl > xrpl.protocol
tests.libxrpl > xrpl.protocol_autogen
tests.libxrpl > xrpl.resource
@@ -206,6 +197,10 @@ tests.libxrpl > xrpl.tx
xrpl.conditions > xrpl.basics
xrpl.conditions > xrpl.protocol
xrpl.config > xrpl.basics
xrpl.consensus > xrpl.basics
xrpl.consensus > xrpl.json
xrpl.consensus > xrpl.ledger
xrpl.consensus > xrpl.protocol
xrpl.core > xrpl.basics
xrpl.core > xrpl.json
xrpl.core > xrpl.protocol
@@ -220,6 +215,8 @@ xrpl.nodestore > xrpl.basics
xrpl.nodestore > xrpl.config
xrpl.nodestore > xrpl.json
xrpl.nodestore > xrpl.protocol
xrpl.peerfinder > xrpl.basics
xrpl.peerfinder > xrpl.protocol
xrpl.protocol > xrpl.basics
xrpl.protocol > xrpl.json
xrpl.protocol_autogen > xrpl.json
@@ -246,23 +243,20 @@ xrpl.tx > xrpl.protocol
xrpld.app > test.unit_test
xrpld.app > xrpl.basics
xrpld.app > xrpl.config
xrpld.app > xrpl.consensus
xrpld.app > xrpl.core
xrpld.app > xrpld.consensus
xrpld.app > xrpld.core
xrpld.app > xrpl.json
xrpld.app > xrpl.ledger
xrpld.app > xrpl.net
xrpld.app > xrpl.nodestore
xrpld.app > xrpl.peerfinder
xrpld.app > xrpl.protocol
xrpld.app > xrpl.rdb
xrpld.app > xrpl.resource
xrpld.app > xrpl.server
xrpld.app > xrpl.shamap
xrpld.app > xrpl.tx
xrpld.consensus > xrpl.basics
xrpld.consensus > xrpl.json
xrpld.consensus > xrpl.ledger
xrpld.consensus > xrpl.protocol
xrpld.core > xrpl.basics
xrpld.core > xrpl.config
xrpld.core > xrpl.core
@@ -271,21 +265,22 @@ xrpld.core > xrpl.protocol
xrpld.core > xrpl.rdb
xrpld.overlay > xrpl.basics
xrpld.overlay > xrpl.config
xrpld.overlay > xrpl.consensus
xrpld.overlay > xrpl.core
xrpld.overlay > xrpld.consensus
xrpld.overlay > xrpld.core
xrpld.overlay > xrpld.peerfinder
xrpld.overlay > xrpl.json
xrpld.overlay > xrpl.ledger
xrpld.overlay > xrpl.peerfinder
xrpld.overlay > xrpl.protocol
xrpld.overlay > xrpl.resource
xrpld.overlay > xrpl.server
xrpld.overlay > xrpl.shamap
xrpld.overlay > xrpl.tx
xrpld.peerfinder > xrpl.basics
xrpld.peerfinder > xrpl.config
xrpld.peerfinder > xrpld.app
xrpld.peerfinder > xrpld.core
xrpld.peerfinder > xrpl.protocol
xrpld.peerfinder > xrpl.peerfinder
xrpld.peerfinder > xrpl.rdb
xrpld.perflog > xrpl.basics
xrpld.perflog > xrpl.config

View File

@@ -46,9 +46,6 @@ for DIRECTORY in "${DIRECTORIES[@]}"; do
done
done
# Special case for NuDBFactory that has ripple twice in the test suite name.
${SED_COMMAND} -i -E 's/(BEAST_DEFINE_TESTSUITE.+)ripple(.+)/\1xrpl\2/g' src/test/nodestore/NuDBFactory_test.cpp
DIRECTORY=$1
find "${DIRECTORY}" -type f -name "*.md" | while read -r FILE; do
echo "Processing file: ${FILE}"

View File

@@ -1,13 +1,22 @@
{
"image_tag": "sha-3122de8",
"image_tag": "sha-fecfc0c",
"configs": {
"ubuntu": [
{
"compiler": ["gcc"],
"build_type": ["Debug"],
"arch": ["amd64"],
"minimal": true,
"suffix": "coverage",
"extra_cmake_args": "-DUNIT_TEST_REFERENCE_FEE=500 -Dcoverage=ON -Dcoverage_format=xml -DCODE_COVERAGE_VERBOSE=ON -DCMAKE_C_FLAGS=-O0 -DCMAKE_CXX_FLAGS=-O0"
},
{
"compiler": ["clang"],
"build_type": ["Release"],
"arch": ["amd64"],
"minimal": true
},
{
"compiler": ["gcc"],
"build_type": ["Release"],
@@ -29,14 +38,6 @@
"sanitizers": ["address", "undefinedbehavior"]
},
{
"compiler": ["gcc"],
"build_type": ["Debug"],
"arch": ["amd64"],
"minimal": true,
"suffix": "coverage",
"extra_cmake_args": "-DUNIT_TEST_REFERENCE_FEE=500 -Dcoverage=ON -Dcoverage_format=xml -DCODE_COVERAGE_VERBOSE=ON -DCMAKE_C_FLAGS=-O0 -DCMAKE_CXX_FLAGS=-O0"
},
{
"compiler": ["clang"],
"build_type": ["Debug"],

View File

@@ -13,6 +13,7 @@ on:
- "!nix/docker/README.md"
- "!nix/devshell.nix"
- "bin/check-tools.sh"
- "bin/default-loader-path.sh"
- "bin/install-sanitizer-libs.sh"
pull_request:
paths:
@@ -24,6 +25,7 @@ on:
- "!nix/docker/README.md"
- "!nix/devshell.nix"
- "bin/check-tools.sh"
- "bin/default-loader-path.sh"
- "bin/install-sanitizer-libs.sh"
workflow_dispatch:

View File

@@ -23,7 +23,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Write PR body to file
env:

114
.github/workflows/check-tools.yml vendored Normal file
View File

@@ -0,0 +1,114 @@
# Verifies the committed snapshots of `bin/check-tools.sh` output for each Nix
# environment (see nix/check-tools/). If the environment changes — a new image
# tag, an updated flake.lock, a different tool list — without the matching
# snapshot being regenerated and committed, this workflow fails so the drift is
# caught in review.
#
# To regenerate the snapshots, see nix/check-tools/README.md.
name: Check tools
on:
pull_request:
paths:
- ".github/workflows/check-tools.yml"
- ".github/scripts/strategy-matrix/linux.json"
- "bin/check-tools.sh"
- "nix/**"
- "flake.nix"
- "flake.lock"
- "rust-toolchain.toml"
push:
branches:
- "develop"
paths:
- ".github/workflows/check-tools.yml"
- ".github/scripts/strategy-matrix/linux.json"
- "bin/check-tools.sh"
- "nix/**"
- "flake.nix"
- "flake.lock"
- "rust-toolchain.toml"
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
defaults:
run:
shell: bash
jobs:
# The nix-nixos image tag is pinned alongside the build matrix in linux.json,
# so snapshots are checked against the exact image CI builds against.
linux-image-tag:
runs-on: ubuntu-latest
outputs:
tag: ${{ steps.tag.outputs.tag }}
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Read nix image tag
id: tag
run: echo "tag=$(jq -r .image_tag .github/scripts/strategy-matrix/linux.json)" >>"${GITHUB_OUTPUT}"
# One job for all environments; they differ only in whether the tools come
# from the nix-nixos container (Linux) or `nix develop` (macOS).
check-tools:
needs: linux-image-tag
strategy:
fail-fast: false
matrix:
include:
- runner: ubuntu-latest
snapshot: nix/check-tools/nix-ubuntu-amd64.txt
nix_develop: false
- runner: ubuntu-24.04-arm
snapshot: nix/check-tools/nix-ubuntu-arm64.txt
nix_develop: false
- runner: macos-26-apple-clang-21
snapshot: nix/check-tools/macos.txt
nix_develop: true
runs-on: ${{ matrix.runner }}
# Linux runs inside the pinned nix-nixos image; macOS runs natively and uses
# the flake's dev shell instead (see the run step below).
container: ${{ !matrix.nix_develop && format('ghcr.io/xrplf/xrpld/nix-ubuntu:{0}', needs.linux-image-tag.outputs.tag) || null }}
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@c00c22ada3bd6bcda48fcb0d62fbbab49fec8a0f
with:
enable_ccache: false
- name: Regenerate snapshot
env:
CHECK_TOOLS_SKIP_CLONE: "1"
# check-tools.sh skips some macOS tools when CI is set; the snapshots
# capture the full `nix develop` environment, so unset it here.
CI: ""
run: |
if [ "${{ matrix.nix_develop }}" = "true" ]; then
# `nix develop` prints the dev-shell greeting first; keep only the
# check-tools.sh output (from the "Detected OS:" line onward).
nix --extra-experimental-features "nix-command flakes" develop \
-c bash bin/check-tools.sh | sed -n '/^Detected OS:/,$p' >"${{ matrix.snapshot }}"
else
bash bin/check-tools.sh >"${{ matrix.snapshot }}"
fi
- name: Verify snapshot is up to date
run: |
if ! git diff --exit-code -- "${{ matrix.snapshot }}"; then
echo "::error::${{ matrix.snapshot }} is out of date. Regenerate it (see nix/check-tools/README.md) and commit the result."
exit 1
fi
- name: Upload regenerated snapshot
if: failure()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: check-tools-${{ runner.os }}-${{ runner.arch }}
path: ${{ matrix.snapshot }}

View File

@@ -52,7 +52,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Determine changed files
# This step checks whether any files have changed that should
# cause the next jobs to run. We do it this way rather than
@@ -90,6 +90,7 @@ jobs:
.clang-tidy
.codecov.yml
bin/check-tools.sh
bin/default-loader-path.sh
cfg/**
cmake/**
conan/**

View File

@@ -28,6 +28,7 @@ on:
- ".clang-tidy"
- ".codecov.yml"
- "bin/check-tools.sh"
- "bin/default-loader-path.sh"
- "cfg/**"
- "cmake/**"
- "conan/**"

View File

@@ -41,13 +41,13 @@ env:
jobs:
build:
runs-on: ubuntu-latest
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-3122de8
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-fecfc0c
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@e4b6449d55a61c002d7c3fdfa6c20f721ede0606
uses: XRPLF/actions/prepare-runner@c00c22ada3bd6bcda48fcb0d62fbbab49fec8a0f
with:
enable_ccache: false

View File

@@ -110,10 +110,10 @@ jobs:
uses: XRPLF/actions/cleanup-workspace@c7d9ce5ebb03c752a354889ecd870cadfc2b1cd4
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@e4b6449d55a61c002d7c3fdfa6c20f721ede0606
uses: XRPLF/actions/prepare-runner@c00c22ada3bd6bcda48fcb0d62fbbab49fec8a0f
with:
enable_ccache: ${{ inputs.ccache_enabled }}
@@ -266,7 +266,7 @@ jobs:
./xrpld --definitions | python3 -m json.tool >server_definitions.json
- name: Upload server definitions
if: ${{ github.event.repository.visibility == 'public' && inputs.config_name == 'debian-gcc-release-amd64' }}
if: ${{ github.event.repository.visibility == 'public' && inputs.config_name == 'ubuntu-gcc-debug-amd64-coverage' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: server-definitions

View File

@@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Check levelization
run: python .github/scripts/levelization/generate.py
- name: Check for differences

View File

@@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Check definitions
run: .github/scripts/rename/definitions.sh .
- name: Check copyright notices

View File

@@ -34,16 +34,16 @@ jobs:
needs: [determine-files]
if: ${{ needs.determine-files.outputs.cpp_changed_files != '' || needs.determine-files.outputs.need_full_run == 'true' }}
runs-on: ["self-hosted", "Linux", "X64", "heavy"]
container: "ghcr.io/xrplf/xrpld/nix-debian:sha-3122de8"
container: "ghcr.io/xrplf/xrpld/nix-debian:sha-fecfc0c"
permissions:
contents: read
issues: write
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@e4b6449d55a61c002d7c3fdfa6c20f721ede0606
uses: XRPLF/actions/prepare-runner@c00c22ada3bd6bcda48fcb0d62fbbab49fec8a0f
with:
enable_ccache: false
@@ -95,7 +95,7 @@ jobs:
TARGETS: ${{ needs.determine-files.outputs.need_full_run != 'true' && needs.determine-files.outputs.cpp_changed_files || 'include src tests' }}
run: |
set -o pipefail
run-clang-tidy -j ${{ steps.nproc.outputs.nproc }} -p "${BUILD_DIR}" -quiet -fix -allow-no-checks ${TARGETS} 2>&1 | tee "${OUTPUT_FILE}"
run-clang-tidy -j ${{ steps.nproc.outputs.nproc }} -p "${BUILD_DIR}" -quiet -fix -format -allow-no-checks ${TARGETS} 2>&1 | tee "${OUTPUT_FILE}"
- name: Print filtered clang-tidy errors
if: ${{ steps.run_clang_tidy.outcome != 'success' }}

View File

@@ -27,7 +27,7 @@ jobs:
matrix: ${{ steps.generate.outputs.matrix }}
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
@@ -54,7 +54,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Download pre-built binary
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1

View File

@@ -23,7 +23,7 @@ jobs:
matrix: ${{ steps.generate.outputs.matrix }}
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0

View File

@@ -40,14 +40,14 @@ defaults:
jobs:
upload:
runs-on: ubuntu-latest
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-3122de8
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-fecfc0c
env:
REMOTE_NAME: ${{ inputs.remote_name }}
CONAN_LOGIN_USERNAME_XRPLF: ${{ secrets.remote_username }}
CONAN_PASSWORD_XRPLF: ${{ secrets.remote_password }}
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Generate build version number
id: version

View File

@@ -65,10 +65,10 @@ jobs:
uses: XRPLF/actions/cleanup-workspace@c7d9ce5ebb03c752a354889ecd870cadfc2b1cd4
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@e4b6449d55a61c002d7c3fdfa6c20f721ede0606
uses: XRPLF/actions/prepare-runner@c00c22ada3bd6bcda48fcb0d62fbbab49fec8a0f
with:
enable_ccache: false

View File

@@ -42,6 +42,8 @@ Our Linux CI tooling is distro-independent and uses a Nix-based environment, so
### macOS
Many `xrpld` engineers use macOS for development.
The minimum supported version is macOS 15 (Sequoia).
CI testing is done in macOS 26 (Tahoe), but the build defaults `CMAKE_OSX_DEPLOYMENT_TARGET` to 15.
### Windows

View File

@@ -13,6 +13,23 @@ if(DEFINED CMAKE_MODULE_PATH)
endif()
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
# Must be set before project() because project() consumes it when configuring the compiler and SDK.
# A user-provided -DCMAKE_OSX_DEPLOYMENT_TARGET still takes precedence.
#
# CMAKE_SYSTEM_NAME can't be used before project(), so CMAKE_HOST_SYSTEM_NAME is used instead.
#
# When CMAKE_OSX_DEPLOYMENT_TARGET is bumped to >=26.0, FastFloat dependency won't be needed anymore
if(
CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin"
AND NOT DEFINED CMAKE_OSX_DEPLOYMENT_TARGET
)
set(CMAKE_OSX_DEPLOYMENT_TARGET
"15.0"
CACHE STRING
"Minimum macOS deployment version"
)
endif()
project(xrpl)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD 23)
@@ -87,6 +104,7 @@ include(deps/Boost)
add_subdirectory(external/antithesis-sdk)
find_package(date REQUIRED)
find_package(ed25519 REQUIRED)
find_package(FastFloat REQUIRED)
find_package(gRPC REQUIRED)
find_package(LibArchive REQUIRED)
find_package(lz4 REQUIRED)
@@ -102,6 +120,7 @@ target_link_libraries(
xrpl_libs
INTERFACE
ed25519::ed25519
FastFloat::fast_float
lz4::lz4
mpt-crypto::mpt-crypto
OpenSSL::Crypto

View File

@@ -348,12 +348,14 @@ run-clang-tidy -p build -allow-no-checks src tests
```
This will check all source files in the `src`, `include` and `tests` directories using the compile commands from your `build` directory.
If you wish to automatically fix whatever clang-tidy finds _and_ is capable of fixing, add `-fix` to the above command:
If you wish to automatically fix whatever clang-tidy finds _and_ is capable of fixing, add `-fix -format` to the above command:
```
run-clang-tidy -p build -quiet -fix -allow-no-checks src tests
run-clang-tidy -p build -quiet -fix -format -allow-no-checks src tests
```
`-format` reformats the fixed code with [`.clang-format`](./.clang-format); without it the fixes are inserted in LLVM style and the `clang-format` hook rewrites them afterwards.
## Contracts and instrumentation
We are using [Antithesis](https://antithesis.com/) for continuous fuzzing,

View File

@@ -30,8 +30,10 @@ 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.
# Runs the probe (default: "<name> --version"), capturing both stdout and
# stderr, and prints one aligned line: the status, the name, and the first
# non-blank line of the probe output (its version). Records <name> as missing
# if the command is not found or exits non-zero.
check() {
local name="$1"
shift
@@ -40,10 +42,11 @@ check() {
probe=("${name}" --version)
fi
echo "Checking ${name}..."
checked=$((checked + 1))
if "${probe[@]}" | head -n 1; then
printf ' [ ok ] %s\n' "${name}"
local output version
if output="$("${probe[@]}" 2>&1)"; then
version="$(printf '%s\n' "${output}" | grep -m1 '[^[:space:]]' || true)"
printf ' [ ok ] %-20s %s\n' "${name}" "${version}"
else
printf ' [MISS] %s\n' "${name}"
missing+=("${name}")
@@ -85,12 +88,14 @@ if [ "${os}" = "linux" ] || [ "${os}" = "macos" ]; then
check file
check less
check make
check netstat which netstat
# net-tools netstat reports "net-tools X.Y"; macOS ships BSD netstat with no
# version flag, so fall back to a presence marker there.
check netstat sh -c 'command -v netstat >/dev/null && { netstat --version 2>&1 | grep -m1 -oE "net-tools [0-9.]+" || echo present; }'
check ninja
check perl
check perl perl -e 'print "$^V\n"'
check pkg-config
check vim
check zip
check zip bash -c 'zip --version 2>&1 | grep -m1 -oE "Zip [0-9.]+"'
# 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

View File

@@ -144,7 +144,11 @@ def main():
+ files
)
canonicalize_fix_paths(Path(fixes_dir))
applied = subprocess.run([clang_apply_replacements, fixes_dir])
# `FormatStyle` in .clang-tidy does not reach this path,
# so ask for the repository style here.
applied = subprocess.run(
[clang_apply_replacements, "--format", "--style=file", fixes_dir]
)
return result.returncode or applied.returncode

View File

@@ -29,6 +29,27 @@ if(CMAKE_GENERATOR STREQUAL "Xcode")
set(is_xcode TRUE)
endif()
# --------------------------------------------------------------------
# Nix toolchain detection
# --------------------------------------------------------------------
# True when the C++ compiler resolves into the Nix store. CMAKE_CXX_COMPILER may
# be referenced through a symlink outside the store (a Nix profile, a /usr/bin
# alternative, ...), so resolve the real path before matching.
set(is_nix_compiler FALSE)
get_filename_component(_cxx_real "${CMAKE_CXX_COMPILER}" REALPATH)
if(_cxx_real MATCHES "^/nix/store/")
set(is_nix_compiler TRUE)
endif()
unset(_cxx_real)
# True inside the Nix CI Docker image, identified by the /nix/ci-env tree it
# ships (see nix/docker/Dockerfile). The dev shell and bare systems don't have
# it, so it distinguishes the CI image from other Nix-compiler environments.
set(is_ci_image FALSE)
if(EXISTS "/nix/ci-env/bin")
set(is_ci_image TRUE)
endif()
# --------------------------------------------------------------------
# Operating system detection
# --------------------------------------------------------------------

View File

@@ -1,26 +1,37 @@
#[===================================================================[
Patch executables to run in non-Nix environments.
The Nix-based CI image links binaries against an ELF interpreter (loader)
that lives in the Nix store, so the resulting binaries don't run elsewhere
(including once installed from the .deb package). `patch_nix_binary` adds a
POST_BUILD step that resets the interpreter to the system default loader and
drops the rpath.
The Nix toolchain links binaries against an ELF interpreter (loader)
that lives in the Nix store, so the resulting binaries don't run elsewhere.
`patch_nix_binary` adds a POST_BUILD step that resets the interpreter
to the system default loader and drops the rpath.
This is only active inside the Nix-based image, detected by the presence of
/tmp/loader-path.sh (shipped by that image, resolves the default loader). It
is skipped for sanitizer builds, whose runtime libraries are resolved through
the rpath. Everywhere else `patch_nix_binary` is a no-op.
This runs by default for Nix-toolchain builds (determined by whether the compiler resolves under /nix/store/).
Those builds are where binaries get a Nix-store loader.
It is opted out of by setting the XRPLD_NO_PATCH_NIX_BINARY environment variable
the plain Nix dev shells set it, since their binaries link a newer glibc
and must not be retargeted to the system loader.
Non-Nix builds (a system compiler, already using the system loader) and sanitizer builds
(runtime libraries resolved through the rpath) are skipped too.
Everywhere else `patch_nix_binary` is a no-op.
The default loader is resolved by bin/default-loader-path.sh.
#]===================================================================]
include_guard(GLOBAL)
include(CompilationEnv)
# Provided by the Nix-based CI image; prints the system default ELF loader path.
set(_loader_path_script "/tmp/loader-path.sh")
# Resolves the system default ELF loader path for the current architecture.
set(_loader_path_script "${CMAKE_SOURCE_DIR}/bin/default-loader-path.sh")
if(is_linux AND NOT SANITIZERS_ENABLED AND EXISTS "${_loader_path_script}")
if(
is_linux
AND NOT SANITIZERS_ENABLED
AND is_nix_compiler
AND NOT DEFINED ENV{XRPLD_NO_PATCH_NIX_BINARY}
)
execute_process(
COMMAND "${_loader_path_script}"
OUTPUT_VARIABLE DEFAULT_LOADER_PATH

View File

@@ -1,3 +1,5 @@
include_guard()
include(isolate_headers)
# Define a benchmark executable for the module `name`.

View File

@@ -171,9 +171,8 @@ else()
# Clang wrapper supplies those paths itself (via -nostdinc++), so at compile time the
# flag is unused -> Clang errors under our -Werror. At link time the flag IS consumed
# (it selects the C++ runtime), so we move it there instead of dropping it entirely.
get_filename_component(_cxx_real "${CMAKE_CXX_COMPILER}" REALPATH)
if(
_cxx_real MATCHES "^/nix/store/"
is_nix_compiler
AND is_linux
AND is_clang
AND CMAKE_CXX_FLAGS MATCHES "stdlib=libstdc"

View File

@@ -133,6 +133,12 @@ target_link_libraries(
add_module(xrpl resource)
target_link_libraries(xrpl.libxrpl.resource PUBLIC xrpl.libxrpl.protocol)
add_module(xrpl peerfinder)
target_link_libraries(
xrpl.libxrpl.peerfinder
PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.protocol
)
# Level 08
add_module(xrpl net)
target_link_libraries(
@@ -201,6 +207,16 @@ target_link_libraries(
add_module(xrpl tx)
target_link_libraries(xrpl.libxrpl.tx PUBLIC xrpl.libxrpl.ledger)
add_module(xrpl consensus)
target_link_libraries(
xrpl.libxrpl.consensus
PUBLIC
xrpl.libxrpl.basics
xrpl.libxrpl.json
xrpl.libxrpl.protocol
xrpl.libxrpl.ledger
)
add_library(xrpl.libxrpl)
set_target_properties(xrpl.libxrpl PROPERTIES OUTPUT_NAME xrpl)
@@ -220,6 +236,7 @@ target_link_modules(
beast
conditions
config
consensus
core
crypto
git
@@ -227,6 +244,7 @@ target_link_modules(
ledger
net
nodestore
peerfinder
protocol
protocol_autogen
rdb

View File

@@ -36,6 +36,19 @@ elseif(is_gcc)
endif()
endif()
# A Nix compiler is only meant to be used from a managed environment: the xrpld
# dev shell (which exports XRPL_DEVSHELL) or the CI image. Using one from a bare
# shell usually means a leaked toolchain (picked up via PATH or a Conan profile)
# and leads to confusing breakage, so fail early with guidance.
if(is_nix_compiler AND NOT is_ci_image AND NOT DEFINED ENV{XRPL_DEVSHELL})
message(
FATAL_ERROR
"A Nix compiler (${CMAKE_CXX_COMPILER}) is being used outside the xrpld "
"dev shell. Enter it with `nix develop` (see docs/build/nix.md) before "
"configuring the build."
)
endif()
# check for in-source build and fail
if("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
message(

View File

@@ -20,6 +20,7 @@
"jemalloc/5.3.1#1fc58d55316041f10fbc1e8a2eae632a%1776700028.228",
"gtest/1.17.0#5224b3b3ff3b4ce1133cbdd27d53ee7d%1782392402.791979",
"grpc/1.81.1#f729f6d75992d20f9c72828e9142d62f%1783945160.094135",
"fast_float/8.2.10#f6f28d6bb22112078e7dbda611caf681%1782494504.298",
"ed25519/2015.03#ae761bdc52730a843f0809bdf6c1b1f6%1782307148.15562",
"date/3.0.4#862e11e80030356b53c2c38599ceb32b%1782392402.538492",
"c-ares/1.34.6#545240bb1c40e2cacd4362d6b8967650%1782392402.681654",
@@ -34,7 +35,7 @@
"protobuf/6.33.5#ff253ead763bd8d9904a52979cd21e81%1782392410.233933",
"nasm/2.16.01#31e26f2ee3c4346ecd347911bd126904%1782395690.33162",
"msys2/cci.latest#d22fe7b2808f5fd34d0a7923ace9c54f%1770657326.649",
"m4/1.4.19#34c4bbc3eeebe98ca6edf2f52d602e7d%1777282960.259",
"m4/1.4.19#1727f439cf74e83826ec96d0b4904eee%1784541921.659",
"cmake/4.3.3#840cf00ea09777e05c2050a50a82c722%1782392418.696091",
"b2/5.4.2#ffd6084a119587e70f11cd45d1a386e2%1782392402.624226",
"automake/1.16.5#b91b7c384c3deaa9d535be02da14d04f%1755524470.56",

View File

@@ -5,6 +5,13 @@
{% if os == "Linux" %}
{% set compiler_version = detect_api.default_compiler_version(compiler, version) %}
{% endif %}
{% if os == "Macos" %}
{# Minimum macOS the dependencies target. #}
{# Without this, Conan builds each dependency against the (possibly newer) host SDK, so the #}
{# dependency objects target a newer macOS than the binary and the linker warns. #}
{# Keep at or below CMAKE_OSX_DEPLOYMENT_TARGET in CMakeLists.txt. #}
{% set min_macos_version = "15.0" %}
{% endif %}
[settings]
os={{ os }}
@@ -18,6 +25,9 @@ compiler.runtime=static
{% else %}
compiler.libcxx={{ detect_api.detect_libcxx(compiler, version, compiler_exe) }}
{% endif %}
{% if os == "Macos" %}
os.version={{ min_macos_version }}
{% endif %}
[conf]
{# The Boost recipe builds with b2, which doesn't use Conan's toolchain files. #}
@@ -41,3 +51,13 @@ tools.build:compiler_executables={'c':'{{ cc_exe }}','cpp':'{{ cxx_exe }}'}
{# More info: https://docs.conan.io/2/reference/extensions/binary_compatibility.html #}
user.package:cppstd_version=23
tools.info.package_id:confs+=["user.package:cppstd_version"]
{% if os == "Macos" %}
[buildenv]
{# os.version adds -mmacosx-version-min to compiler command lines, #}
{# but Boost.Context's b2 assembly (.S) rule ignores it, #}
{# so those objects keep the host SDK version and still warn at link time. #}
{# clang's assembler honors this env var regardless, pinning them. #}
{# Scoped to boost/* since it is the only gap. #}
boost/*:MACOSX_DEPLOYMENT_TARGET={{ min_macos_version }}
{% endif %}

View File

@@ -29,6 +29,7 @@ class Xrpl(ConanFile):
requires = [
"ed25519/2015.03",
"fast_float/8.2.10",
"grpc/1.81.1",
"libarchive/3.8.7",
"nudb/2.0.9",
@@ -211,6 +212,7 @@ class Xrpl(ConanFile):
"boost::thread",
"date::date",
"ed25519::ed25519",
"fast_float::fast_float",
"grpc::grpc++",
"libarchive::libarchive",
"lz4::lz4",

38
docs/build/nix.md vendored
View File

@@ -38,8 +38,10 @@ The first time you run this command, it will take a few minutes to download and
### 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.
- **Linux**: `nix develop` gives you a shell with all the tooling necessary to develop xrpld
and with the same GCC/glibc toolchain that Nix builds for CI.
See [Choosing a different compiler](#choosing-a-different-compiler)
for the custom-vs-plain toolchain trade-off.
- **macOS**: `nix develop` gives you a full environment too, with Clang (and
every other tool, including Conan) provided by Nix. To use your system-wide
Apple Clang instead, enter `nix develop .#apple-clang`. Conan has no binary in
@@ -63,8 +65,16 @@ The first time you run this command, it will take a few minutes to download and
### Choosing a different compiler
A compiler can be chosen by providing its name with the `.#` prefix, e.g. `nix develop .#clang`.
The `.#gcc` and `.#clang` shells provide the same GCC and Clang versions used in CI
(pinned in [`nix/packages.nix`](../../nix/packages.nix)).
On Linux, `.#gcc` and `.#clang` provide the exact toolchain CI uses:
the compiler (pinned in [`nix/packages.nix`](../../nix/packages.nix))
rebuilt against the pinned custom glibc (see [`nix/compilers.nix`](../../nix/compilers.nix)).
Building that toolchain the first time is slow unless it is fetched from a Nix binary cache.
If you don't need the custom glibc, the Linux-only `.#gcc-plain` and `.#clang-plain`
give you the stock nixpkgs compilers of the same versions.
On macOS there is no custom glibc, so `.#gcc` and `.#clang` are already the plain nixpkgs toolchain,
and the `-plain` variants do not exist.
Use `nix flake show` to see all the available development shells.
Use `nix develop .#no-compiler` to use the compiler from your system.
@@ -72,14 +82,18 @@ Use `nix develop .#no-compiler` to use the compiler from your system.
### Example Usage
```bash
# Use GCC (same version as CI)
# Use GCC same toolchain as CI (custom glibc on Linux)
nix develop .#gcc
# Use Clang (same version as CI)
# Use Clang same toolchain as CI (custom glibc on Linux)
nix develop .#clang
# Use default for your platform
nix develop
# Stock nixpkgs GCC/Clang, Linux only — skips the custom-glibc build, but does not match CI
nix develop .#gcc-plain
nix develop .#clang-plain
```
### Using a different shell
@@ -110,6 +124,10 @@ nix develop -c "$SHELL"
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.).
Coverage builds (`-Dcoverage=ON`) work in the `gcc` shell (and `gcc-plain` on Linux):
each ships a `gcov` matching its compiler, since Nix's cc-wrapper does not expose one.
The `clang` shells do not include `llvm-cov`, so use a `gcc` shell for coverage.
## Automatic Activation with direnv
[direnv](https://direnv.net/) or [nix-direnv](https://github.com/nix-community/nix-direnv) can automatically activate the Nix development shell when you enter the repository directory.
@@ -136,6 +154,14 @@ conan install .. --output-folder . --build '*' --settings build_type=Release
To update `flake.lock` to the latest revision use `nix flake update` command.
## Tooling snapshots
The tool versions in each Nix environment are recorded in
[`nix/check-tools/`](../../nix/check-tools) and verified by CI. If you change the
environment (bump the CI image tag, update `flake.lock`, or edit the tool list in
`bin/check-tools.sh`), CI fails until you regenerate and commit the affected
snapshot — see [`nix/check-tools/README.md`](../../nix/check-tools/README.md).
## Troubleshooting
See [Troubleshooting Nix problems](./nix_troubleshooting.md) for common issues,

View File

@@ -3,6 +3,78 @@
Common issues encountered when using the [Nix development shell](./nix.md), and
how to resolve them.
## `command not found: nix` after a macOS update
If a shell suddenly can't find `nix` at all:
```
$ nix develop
zsh: command not found: nix
```
then Nix is almost certainly still installed — only the shell hook that puts it
on your `PATH` is gone. Confirm that first:
```bash
ls -l /nix/var/nix/profiles/default/bin/nix
```
If that exists, the installation is fine and this is purely a `PATH` problem.
### Why it happens
The installer does not touch your dotfiles. Instead it sources a setup script
from the Nix store by editing **system-wide** rc files:
| Shell | File the installer edits |
| ----- | ------------------------------------- |
| bash | `/etc/bashrc`, `/etc/bash.bashrc` |
| zsh | `/etc/zshrc` |
| fish | `$__fish_sysconf_dir/conf.d/nix.fish` |
macOS manages `/etc/zshrc`, so an OS update can replace it with the vendor copy
and silently drop the Nix block. `/etc/bashrc` and the fish file usually survive,
which is why the breakage often shows up in zsh only. You can verify this by
diffing against the backup the installer left behind:
```bash
diff /etc/zshrc /etc/zshrc.backup-before-nix
```
If they are identical, the Nix snippet was wiped. This is upstream issue
[NixOS/nix#3616](https://github.com/NixOS/nix/issues/3616).
### Fix
To unblock the current shell:
```bash
. /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
```
For a permanent fix, add the snippet to your **user** rc file rather than
restoring `/etc/zshrc` — user dotfiles are not clobbered by OS updates:
```bash
cat >>~/.zshrc <<'EOF'
# Nix
if [ -e '/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh' ]; then
. '/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh'
fi
# End Nix
EOF
```
The scripts guard against double-sourcing via `__ETC_PROFILE_NIX_SOURCED`, so
this is safe even if a system-wide hook is later restored.
> [!NOTE]
> `/etc/zshrc` and `~/.zshrc` are only read by **interactive** zsh. If the
> snippet is present but `zsh -c '…'`, a script, or an IDE terminal still can't
> find `nix`, that shell is non-interactive — put the snippet in `~/.zshenv`
> instead.
## Git worktrees
If `nix develop` fails with an error like:

View File

@@ -11,7 +11,7 @@ namespace xrpl {
class Resolver
{
public:
using HandlerType = std::function<void(std::string, std::vector<beast::IP::Endpoint>)>;
using HandlerType = std::function<void(std::string, std::vector<beast::ip::Endpoint>)>;
virtual ~Resolver() = 0;

View File

@@ -11,6 +11,7 @@
#include <limits>
#include <stdexcept>
#include <string>
#include <string_view>
#include <type_traits>
#include <vector>
@@ -251,4 +252,11 @@ makeSlice(std::basic_string<char, Traits, Alloc> const& s)
return Slice(s.data(), s.size());
}
template <class Traits>
Slice
makeSlice(std::basic_string_view<char, Traits> s)
{
return Slice(s.data(), s.size());
}
} // namespace xrpl

View File

@@ -5,6 +5,7 @@
#include <xrpl/beast/container/detail/aged_associative_container.h>
#include <xrpl/beast/container/detail/aged_container_iterator.h>
#include <xrpl/beast/container/detail/empty_base_optimization.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/unordered_set.hpp>

View File

@@ -58,7 +58,7 @@ struct LexicalCast<Out, std::string_view>
"beast::LexicalCast can only be used with integral types");
template <class Integral = Out>
bool
constexpr bool
operator()(Integral& out, std::string_view in) const
requires(std::is_integral_v<Integral> && !std::is_same_v<Integral, bool>)
{
@@ -110,7 +110,7 @@ struct LexicalCast<Out, boost::core::basic_string_view<char>>
{
explicit LexicalCast() = default;
bool
constexpr bool
operator()(Out& out, boost::core::basic_string_view<char> in) const
{
return LexicalCast<Out, std::string_view>()(out, in);
@@ -123,7 +123,7 @@ struct LexicalCast<Out, std::string>
{
explicit LexicalCast() = default;
bool
constexpr bool
operator()(Out& out, std::string in) const
{
return LexicalCast<Out, std::string_view>()(out, in);
@@ -136,7 +136,7 @@ struct LexicalCast<Out, char const*>
{
explicit LexicalCast() = default;
bool
constexpr bool
operator()(Out& out, char const* in) const
{
XRPL_ASSERT(in, "beast::detail::LexicalCast(char const*) : non-null input");
@@ -151,7 +151,7 @@ struct LexicalCast<Out, char*>
{
explicit LexicalCast() = default;
bool
constexpr bool
operator()(Out& out, char* in) const
{
XRPL_ASSERT(in, "beast::detail::LexicalCast(char*) : non-null input");
@@ -177,7 +177,7 @@ struct BadLexicalCast : public std::bad_cast
* @return `false` if there was a parsing or range error
*/
template <class Out, class In>
bool
constexpr bool
lexicalCastChecked(Out& out, In in)
{
return detail::LexicalCast<Out, In>()(out, in);
@@ -191,7 +191,7 @@ lexicalCastChecked(Out& out, In in)
* @return The new type.
*/
template <class Out, class In>
Out
constexpr Out
lexicalCastThrow(In in)
{
if (Out out; lexicalCastChecked(out, in))
@@ -207,7 +207,7 @@ lexicalCastThrow(In in)
* @return The new type.
*/
template <class Out, class In>
Out
constexpr Out
lexicalCast(In in, Out defaultValue = Out())
{
if (Out out; lexicalCastChecked(out, in))

View File

@@ -17,14 +17,14 @@ namespace beast {
class SemanticVersion
{
public:
using identifier_list = std::vector<std::string>;
using IdentifierList = std::vector<std::string>;
int majorVersion;
int minorVersion;
int patchVersion;
identifier_list preReleaseIdentifiers;
identifier_list metaData;
IdentifierList preReleaseIdentifiers;
IdentifierList metaData;
SemanticVersion();

View File

@@ -26,7 +26,7 @@ public:
* @param journal Destination for logging output.
*/
static std::shared_ptr<StatsDCollector>
make(IP::Endpoint const& address, std::string const& prefix, Journal journal);
make(ip::Endpoint const& address, std::string const& prefix, Journal journal);
};
} // namespace beast::insight

View File

@@ -15,7 +15,7 @@
//------------------------------------------------------------------------------
namespace beast {
namespace IP {
namespace ip {
using Address = boost::asio::ip::address;
@@ -73,13 +73,13 @@ isPublic(Address const& addr)
return (addr.is_v4()) ? isPublic(addr.to_v4()) : isPublic(addr.to_v6());
}
} // namespace IP
} // namespace ip
//------------------------------------------------------------------------------
template <class Hasher>
void
hash_append(Hasher& h, beast::IP::Address const& addr) noexcept
hash_append(Hasher& h, beast::ip::Address const& addr) noexcept
{
using beast::hash_append;
if (addr.is_v4())
@@ -101,12 +101,12 @@ hash_append(Hasher& h, beast::IP::Address const& addr) noexcept
namespace boost {
template <>
struct hash<::beast::IP::Address>
struct hash<::beast::ip::Address>
{
explicit hash() = default;
std::size_t
operator()(::beast::IP::Address const& addr) const
operator()(::beast::ip::Address const& addr) const
{
return ::beast::Uhash<>{}(addr);
}

View File

@@ -4,7 +4,7 @@
#include <boost/asio.hpp>
namespace beast::IP {
namespace beast::ip {
/**
* Convert to Endpoint.
@@ -32,7 +32,7 @@ toAsioAddress(Endpoint const& endpoint);
boost::asio::ip::tcp::endpoint
toAsioEndpoint(Endpoint const& endpoint);
} // namespace beast::IP
} // namespace beast::ip
namespace beast {
@@ -41,25 +41,25 @@ struct IPAddressConversion
{
explicit IPAddressConversion() = default;
static IP::Endpoint
static ip::Endpoint
fromAsio(boost::asio::ip::address const& address)
{
return IP::fromAsio(address);
return ip::fromAsio(address);
}
static IP::Endpoint
static ip::Endpoint
fromAsio(boost::asio::ip::tcp::endpoint const& endpoint)
{
return IP::fromAsio(endpoint);
return ip::fromAsio(endpoint);
}
static boost::asio::ip::address
toAsioAddress(IP::Endpoint const& address)
toAsioAddress(ip::Endpoint const& address)
{
return IP::toAsioAddress(address);
return ip::toAsioAddress(address);
}
static boost::asio::ip::tcp::endpoint
toAsioEndpoint(IP::Endpoint const& address)
toAsioEndpoint(ip::Endpoint const& address)
{
return IP::toAsioEndpoint(address);
return ip::toAsioEndpoint(address);
}
};

View File

@@ -2,7 +2,7 @@
#include <boost/asio/ip/address_v4.hpp>
namespace beast::IP {
namespace beast::ip {
using AddressV4 = boost::asio::ip::address_v4;
@@ -25,4 +25,4 @@ isPublic(AddressV4 const& addr);
char
getClass(AddressV4 const& address);
} // namespace beast::IP
} // namespace beast::ip

View File

@@ -2,7 +2,7 @@
#include <boost/asio/ip/address_v6.hpp>
namespace beast::IP {
namespace beast::ip {
using AddressV6 = boost::asio::ip::address_v6;
@@ -18,4 +18,4 @@ isPrivate(AddressV6 const& addr);
bool
isPublic(AddressV6 const& addr);
} // namespace beast::IP
} // namespace beast::ip

View File

@@ -13,7 +13,7 @@
#include <optional>
#include <string>
namespace beast::IP {
namespace beast::ip {
using Port = std::uint16_t;
@@ -223,7 +223,7 @@ operator<<(OutputStream& os, Endpoint const& endpoint)
std::istream&
operator>>(std::istream& is, Endpoint& endpoint);
} // namespace beast::IP
} // namespace beast::ip
//------------------------------------------------------------------------------
@@ -232,12 +232,12 @@ namespace std {
* std::hash support.
*/
template <>
struct hash<::beast::IP::Endpoint>
struct hash<::beast::ip::Endpoint>
{
hash() = default;
std::size_t
operator()(::beast::IP::Endpoint const& endpoint) const
operator()(::beast::ip::Endpoint const& endpoint) const
{
return ::beast::Uhash<>{}(endpoint);
}
@@ -249,12 +249,12 @@ namespace boost {
* boost::hash support.
*/
template <>
struct hash<::beast::IP::Endpoint>
struct hash<::beast::ip::Endpoint>
{
hash() = default;
std::size_t
operator()(::beast::IP::Endpoint const& endpoint) const
operator()(::beast::ip::Endpoint const& endpoint) const
{
return ::beast::Uhash<>{}(endpoint);
}

View File

@@ -295,6 +295,20 @@ public:
return runner_->arg();
}
protected:
/**
* Lets a suite compose other suites (e.g. an aggregator that reruns a
* group of related suites under its own name) via `SuiteInfo::run`.
*
* @return The runner this suite is executing under.
*/
Runner&
runner() const
{
return *runner_;
}
public:
/**
* DEPRECATED
* @return `true` if the test condition indicates success(a false value)

View File

@@ -10,7 +10,7 @@
namespace xrpl {
template <class TxID, class Sequence>
class RCLCensorshipDetector
class CensorshipDetector
{
public:
struct TxIDSeq
@@ -49,7 +49,7 @@ private:
TxIDSeqVec tracker_;
public:
RCLCensorshipDetector() = default;
CensorshipDetector() = default;
/**
* Add transactions being proposed for the current consensus round.

View File

@@ -1,15 +1,14 @@
#pragma once
#include <xrpld/consensus/ConsensusParms.h>
#include <xrpld/consensus/ConsensusProposal.h>
#include <xrpld/consensus/ConsensusTypes.h>
#include <xrpl/basics/Log.h>
#include <xrpl/basics/UnorderedContainers.h>
#include <xrpl/basics/chrono.h>
#include <xrpl/beast/clock/abstract_clock.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/consensus/ConsensusParms.h>
#include <xrpl/consensus/ConsensusProposal.h>
#include <xrpl/consensus/ConsensusTypes.h>
#include <xrpl/json/json_value.h>
#include <xrpl/json/json_writer.h>
#include <xrpl/ledger/LedgerTiming.h>

View File

@@ -1,11 +1,10 @@
#pragma once
#include <xrpld/consensus/ConsensusProposal.h>
#include <xrpld/consensus/DisputedTx.h>
#include <xrpl/basics/UnorderedContainers.h>
#include <xrpl/basics/chrono.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/consensus/ConsensusProposal.h>
#include <xrpl/consensus/DisputedTx.h>
#include <chrono>
#include <cstddef>

View File

@@ -1,9 +1,8 @@
#pragma once
#include <xrpld/consensus/ConsensusParms.h>
#include <xrpl/basics/Log.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/consensus/ConsensusParms.h>
#include <xrpl/json/json_value.h>
#include <xrpl/json/json_writer.h>

View File

@@ -1,7 +1,5 @@
#pragma once
#include <xrpld/consensus/LedgerTrie.h>
#include <xrpl/basics/Log.h>
#include <xrpl/basics/UnorderedContainers.h>
#include <xrpl/basics/chrono.h>
@@ -11,6 +9,7 @@
#include <xrpl/beast/hash/uhash.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/consensus/LedgerTrie.h>
#include <xrpl/json/json_value.h>
#include <algorithm>

View File

@@ -15,12 +15,12 @@
namespace xrpl {
// Forward declarations
namespace NodeStore {
namespace node_store {
class Database;
} // namespace NodeStore
namespace Resource {
} // namespace node_store
namespace resource {
class Manager;
} // namespace Resource
} // namespace resource
namespace perf {
class PerfLog;
} // namespace perf
@@ -160,11 +160,11 @@ public:
virtual PeerReservationTable&
getPeerReservations() = 0;
virtual Resource::Manager&
virtual resource::Manager&
getResourceManager() = 0;
// Storage services
virtual NodeStore::Database&
virtual node_store::Database&
getNodeStore() = 0;
virtual SHAMapStore&

View File

@@ -623,6 +623,7 @@ class ValueConstIterator : public ValueIteratorBase
public:
using size_t = unsigned int;
using difference_type = int;
using value_type = Value const;
using reference = Value const&;
using pointer = Value const*;
using SelfType = ValueConstIterator;
@@ -687,6 +688,7 @@ class ValueIterator : public ValueIteratorBase
public:
using size_t = unsigned int;
using difference_type = int;
using value_type = Value;
using reference = Value&;
using pointer = Value*;
using SelfType = ValueIterator;

View File

@@ -286,6 +286,77 @@ computeFullPaymentInterest(
std::uint32_t startDate,
TenthBips32 closeInterestRate);
// Deltas applied to Vault.AssetsTotal and LoanBroker.DebtTotal at a single
// accounting touch point (origination, payment, impair/unimpair/default).
struct AccountingDeltas
{
Number assetsTotalDelta;
Number debtTotalDelta;
};
// Whole-life (pre-LendingProtocolV1_1) recognition model: interest is
// recognized into AssetsTotal/DebtTotal up front, at origination.
namespace accrual {
// LoanSet origination: what's added to Vault.AssetsTotal and LoanBroker.DebtTotal
AccountingDeltas
loanOriginationDeltas(Number const& principalRequested, Number const& interestDue);
// LoanSet origination: would recognizing this loan's interest push
// Vault.AssetsTotal past Vault.AssetsMaximum?
bool
loanOriginationExceedsVaultMaximum(
Number const& vaultMaximum,
Number const& vaultTotal,
Number const& interestDue);
// LoanManage impair/unimpair/default: the vault's exposure to this loan
Number
loanVaultExposure(SLE::const_ref loanSle);
// LoanPay: what's added to Vault.AssetsTotal and subtracted from LoanBroker.DebtTotal for a payment
AccountingDeltas
loanPaymentDeltas(LoanPaymentParts const& parts);
} // namespace accrual
// Cash-basis (LendingProtocolV1_1) recognition model: AssetsTotal/DebtTotal
// are principal-only, interest is recognized only as it's actually paid.
namespace cash_basis {
AccountingDeltas
loanOriginationDeltas(Number const& principalRequested);
Number
loanVaultExposure(SLE::const_ref loanSle);
AccountingDeltas
loanPaymentDeltas(LoanPaymentParts const& parts);
} // namespace cash_basis
// Public dispatchers: pick cash_basis:: if featureLendingProtocolV1_1 is
// enabled AND the Vault's LEVersion (VaultHelpers::getVaultVersion) is
// VaultVersion::CashBasis, else accrual::. These are the only entry points
// transactors call.
AccountingDeltas
loanOriginationDeltas(
SLE::const_ref vaultSle,
Number const& principalRequested,
Number const& interestDue);
bool
loanOriginationExceedsVaultMaximum(
SLE::const_ref vaultSle,
Number const& vaultTotal,
Number const& interestDue);
Number
loanVaultExposure(SLE::const_ref vaultSle, SLE::const_ref loanSle);
AccountingDeltas
loanPaymentDeltas(SLE::const_ref vaultSle, LoanPaymentParts const& parts);
namespace detail {
// These classes and functions should only be accessed by LendingHelper
// functions and unit tests

View File

@@ -1,5 +1,6 @@
#pragma once
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/protocol/AccountID.h>
@@ -201,4 +202,16 @@ getLedgerEntryOwnerCount(SLE const& sle);
SF_ACCOUNT const&
getLedgerEntrySponsorField(SLE const& sle, AccountID const& owner);
/**
* Delete a Sponsorship (ltSPONSORSHIP) ledger object cleanly.
*
* Unlinks the object from both the sponsor's and sponsee's owner directories,
* releases the sponsor's owner reserve, refunds any prefunded sfFeeAmount to
* the sponsor, and erases the object. Shared by SponsorshipSet (tfDeleteObject)
* and AccountDelete's non-obligation deleter so a sponsored or sponsoring
* account can be deleted without its Sponsorship object blocking it.
*/
[[nodiscard]] TER
deleteSponsorshipObject(ApplyView& view, SLE::ref sle, beast::Journal j);
} // namespace xrpl

View File

@@ -2,6 +2,7 @@
#include <xrpl/ledger/ReadView.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Protocol.h>
#include <xrpl/protocol/STAmount.h>
#include <xrpl/protocol/STLedgerEntry.h>
@@ -107,4 +108,19 @@ sharesToAssetsWithdraw(
[[nodiscard]] bool
isSoleShareholder(ReadView const& view, AccountID const& account, SLE::const_ref issuance);
/**
* Resolves a Vault's LEVersion, the single point every accounting touch
* point should call to determine which recognition model (accrual vs.
* cash-basis) a Vault uses. Vaults created before featureLendingProtocolV1_1
* activated never have sfLEVersion set, which resolves here to
* VaultVersion::Legacy.
*
* @param vault The vault SLE.
*
* @return The Vault's LEVersion, or VaultVersion::Legacy if the field is
* absent.
*/
[[nodiscard]] VaultVersion
getVaultVersion(SLE::const_ref vault);
} // namespace xrpl

View File

@@ -67,16 +67,16 @@ public:
return socket_->next_layer();
}
beast::IP::Endpoint
beast::ip::Endpoint
localEndpoint()
{
return beast::IP::fromAsio(lowestLayer().local_endpoint());
return beast::ip::fromAsio(lowestLayer().local_endpoint());
}
beast::IP::Endpoint
beast::ip::Endpoint
remoteEndpoint()
{
return beast::IP::fromAsio(lowestLayer().remote_endpoint());
return beast::ip::fromAsio(lowestLayer().remote_endpoint());
}
lowest_layer_type&

View File

@@ -13,7 +13,7 @@
#include <stdexcept>
#include <string>
namespace xrpl::NodeStore {
namespace xrpl::node_store {
/**
* A backend used for the NodeStore.
@@ -163,4 +163,4 @@ public:
fdRequired() const = 0;
};
} // namespace xrpl::NodeStore
} // namespace xrpl::node_store

View File

@@ -25,7 +25,7 @@ namespace xrpl {
class Section;
} // namespace xrpl
namespace xrpl::NodeStore {
namespace xrpl::node_store {
/**
* Persistency layer for NodeObject
@@ -248,7 +248,7 @@ protected:
void
storeStats(std::uint64_t count, std::uint64_t sz)
{
XRPL_ASSERT(count <= sz, "xrpl::NodeStore::Database::storeStats : valid inputs");
XRPL_ASSERT(count <= sz, "xrpl::node_store::Database::storeStats : valid inputs");
storeCount_ += count;
storeSz_ += sz;
}
@@ -308,4 +308,4 @@ private:
threadEntry();
};
} // namespace xrpl::NodeStore
} // namespace xrpl::node_store

View File

@@ -9,7 +9,7 @@
#include <memory>
#include <string>
namespace xrpl::NodeStore {
namespace xrpl::node_store {
/* This class has two key-value store Backend objects for persisting SHAMap
* records. This facilitates online deletion of data. New backends are
@@ -38,7 +38,7 @@ public:
*/
virtual void
rotate(
std::unique_ptr<NodeStore::Backend>&& newBackend,
std::unique_ptr<node_store::Backend>&& newBackend,
std::function<void(std::string const& writableName, std::string const& archiveName)> const&
f) = 0;
@@ -56,4 +56,4 @@ public:
setRotationInFlight(bool inFlight) = 0;
};
} // namespace xrpl::NodeStore
} // namespace xrpl::node_store

View File

@@ -3,7 +3,7 @@
#include <xrpl/nodestore/Scheduler.h>
#include <xrpl/nodestore/Task.h>
namespace xrpl::NodeStore {
namespace xrpl::node_store {
/**
* Simple NodeStore Scheduler that just performs the tasks synchronously.
@@ -21,4 +21,4 @@ public:
onBatchWrite(BatchWriteReport const& report) override;
};
} // namespace xrpl::NodeStore
} // namespace xrpl::node_store

View File

@@ -14,7 +14,7 @@ namespace xrpl {
class Section;
} // namespace xrpl
namespace xrpl::NodeStore {
namespace xrpl::node_store {
/**
* Base class for backend factories.
@@ -70,4 +70,4 @@ public:
}
};
} // namespace xrpl::NodeStore
} // namespace xrpl::node_store

View File

@@ -10,7 +10,7 @@
#include <memory>
#include <string>
namespace xrpl::NodeStore {
namespace xrpl::node_store {
/**
* Singleton for managing NodeStore factories and back ends.
@@ -98,4 +98,4 @@ public:
beast::Journal journal) = 0;
};
} // namespace xrpl::NodeStore
} // namespace xrpl::node_store

View File

@@ -8,7 +8,7 @@
#include <cstdint>
#include <memory>
// VFALCO NOTE Intentionally not in the NodeStore namespace
// VFALCO NOTE Intentionally not in the node_store namespace
namespace xrpl {

View File

@@ -4,7 +4,7 @@
#include <chrono>
namespace xrpl::NodeStore {
namespace xrpl::node_store {
enum class FetchType { Synchronous, Async };
@@ -71,4 +71,4 @@ public:
onBatchWrite(BatchWriteReport const& report) = 0;
};
} // namespace xrpl::NodeStore
} // namespace xrpl::node_store

View File

@@ -1,6 +1,6 @@
#pragma once
namespace xrpl::NodeStore {
namespace xrpl::node_store {
/**
* Derived classes perform scheduled tasks.
@@ -17,4 +17,4 @@ struct Task
performScheduledTask() = 0;
};
} // namespace xrpl::NodeStore
} // namespace xrpl::node_store

View File

@@ -5,7 +5,7 @@
#include <memory>
#include <vector>
namespace xrpl::NodeStore {
namespace xrpl::node_store {
// This is only used to pre-allocate the array for
// batch objects and does not affect the amount written.
@@ -36,4 +36,4 @@ enum class Status {
*/
using Batch = std::vector<std::shared_ptr<NodeObject>>;
} // namespace xrpl::NodeStore
} // namespace xrpl::node_store

View File

@@ -9,7 +9,7 @@
#include <memory>
#include <mutex>
namespace xrpl::NodeStore {
namespace xrpl::node_store {
/**
* Batch-writing assist logic.
@@ -86,4 +86,4 @@ private:
Batch writeSet_;
};
} // namespace xrpl::NodeStore
} // namespace xrpl::node_store

View File

@@ -22,7 +22,7 @@
#include <stdexcept>
#include <utility>
namespace xrpl::NodeStore {
namespace xrpl::node_store {
class DatabaseNodeImp : public Database
{
@@ -68,7 +68,7 @@ public:
XRPL_ASSERT(
backend_,
"xrpl::NodeStore::DatabaseNodeImp::DatabaseNodeImp : non-null "
"xrpl::node_store::DatabaseNodeImp::DatabaseNodeImp : non-null "
"backend");
}
@@ -138,4 +138,4 @@ private:
}
};
} // namespace xrpl::NodeStore
} // namespace xrpl::node_store

View File

@@ -16,7 +16,7 @@
#include <mutex>
#include <string>
namespace xrpl::NodeStore {
namespace xrpl::node_store {
class DatabaseRotatingImp : public DatabaseRotating
{
@@ -41,7 +41,7 @@ public:
void
rotate(
std::unique_ptr<NodeStore::Backend>&& newBackend,
std::unique_ptr<node_store::Backend>&& newBackend,
std::function<void(std::string const& writableName, std::string const& archiveName)> const&
f) override;
@@ -94,4 +94,4 @@ private:
forEach(std::function<void(std::shared_ptr<NodeObject>)> f) override;
};
} // namespace xrpl::NodeStore
} // namespace xrpl::node_store

View File

@@ -4,7 +4,7 @@
#include <memory>
namespace xrpl::NodeStore {
namespace xrpl::node_store {
/**
* Parsed key/value blob into NodeObject components.
@@ -49,4 +49,4 @@ private:
int dataBytes_;
};
} // namespace xrpl::NodeStore
} // namespace xrpl::node_store

View File

@@ -12,7 +12,7 @@
#include <memory>
#include <stdexcept>
namespace xrpl::NodeStore {
namespace xrpl::node_store {
/**
* Convert a NodeObject from in-memory to database format.
@@ -68,7 +68,7 @@ class EncodedBlob
public:
explicit EncodedBlob(std::shared_ptr<NodeObject> const& obj)
: size_([&obj]() {
XRPL_ASSERT(obj, "xrpl::NodeStore::EncodedBlob::EncodedBlob : non-null input");
XRPL_ASSERT(obj, "xrpl::node_store::EncodedBlob::EncodedBlob : non-null input");
if (!obj)
throw std::runtime_error("EncodedBlob: unseated std::shared_ptr used.");
@@ -88,7 +88,7 @@ public:
XRPL_ASSERT(
((ptr_ == payload_.data()) && (size_ <= payload_.size())) ||
((ptr_ != payload_.data()) && (size_ > payload_.size())),
"xrpl::NodeStore::EncodedBlob::~EncodedBlob : valid payload "
"xrpl::node_store::EncodedBlob::~EncodedBlob : valid payload "
"pointer");
if (ptr_ != payload_.data())
@@ -114,4 +114,4 @@ public:
}
};
} // namespace xrpl::NodeStore
} // namespace xrpl::node_store

View File

@@ -13,7 +13,7 @@
#include <string>
#include <vector>
namespace xrpl::NodeStore {
namespace xrpl::node_store {
class ManagerImp : public Manager
{
@@ -57,4 +57,4 @@ public:
beast::Journal journal) override;
};
} // namespace xrpl::NodeStore
} // namespace xrpl::node_store

View File

@@ -6,25 +6,25 @@
#include <cstdint>
#include <type_traits>
namespace xrpl::NodeStore {
namespace xrpl::node_store {
// This is a variant of the base128 varint format from
// google protocol buffers:
// https://developers.google.com/protocol-buffers/docs/encoding#varints
// field tag
struct varint;
struct Varint;
// Metafuncton to return largest
// Metafunction to return largest
// possible size of T represented as varint.
// T must be unsigned
template <class T, bool = std::is_unsigned_v<T>>
struct varint_traits;
struct VarintTraits;
template <class T>
struct varint_traits<T, true>
struct VarintTraits<T, true>
{
explicit varint_traits() = default;
explicit VarintTraits() = default;
static constexpr std::size_t kMax = ((8 * sizeof(T)) + 6) / 7;
};
@@ -104,7 +104,7 @@ writeVarint(void* p0, std::size_t v)
template <class T>
void
read(nudb::detail::istream& is, std::size_t& u)
requires(std::is_same_v<T, varint>)
requires(std::is_same_v<T, Varint>)
{
auto p0 = is(1);
auto p1 = p0;
@@ -118,9 +118,9 @@ read(nudb::detail::istream& is, std::size_t& u)
template <class T>
void
write(nudb::detail::ostream& os, std::size_t t)
requires(std::is_same_v<T, varint>)
requires(std::is_same_v<T, Varint>)
{
writeVarint(os.data(sizeVarint(t)), t);
}
} // namespace xrpl::NodeStore
} // namespace xrpl::node_store

View File

@@ -10,7 +10,7 @@
#include <xrpl/basics/contract.h>
#include <xrpl/basics/safe_cast.h>
#include <xrpl/nodestore/NodeObject.h>
#include <xrpl/nodestore/detail/varint.h>
#include <xrpl/nodestore/detail/Varint.h>
#include <xrpl/protocol/HashPrefix.h>
#include <nudb/detail/field.hpp>
@@ -21,7 +21,7 @@
#include <cstring>
#include <string>
namespace xrpl::NodeStore {
namespace xrpl::node_store {
template <class BufferFactory>
std::pair<void const*, std::size_t>
@@ -59,7 +59,7 @@ lz4Compress(void const* in, std::size_t inSize, BufferFactory&& bf)
using std::runtime_error;
using namespace nudb::detail;
std::pair<void const*, std::size_t> result;
std::array<std::uint8_t, varint_traits<std::size_t>::kMax> vi{};
std::array<std::uint8_t, VarintTraits<std::size_t>::kMax> vi{};
auto const n = writeVarint(vi.data(), inSize);
auto const outMax = LZ4_compressBound(inSize);
auto* out = reinterpret_cast<std::uint8_t*>(bf(n + outMax));
@@ -240,7 +240,7 @@ nodeobjectCompress(void const* in, std::size_t inSize, BufferFactory&& bf)
auto* out = reinterpret_cast<std::uint8_t*>(bf(result.second));
result.first = out;
ostream os(out, result.second);
write<varint>(os, type);
write<Varint>(os, type);
write<std::uint16_t>(os, mask);
write(os, vh.data(), n * 32);
return result;
@@ -252,13 +252,13 @@ nodeobjectCompress(void const* in, std::size_t inSize, BufferFactory&& bf)
auto* out = reinterpret_cast<std::uint8_t*>(bf(result.second));
result.first = out;
ostream os(out, result.second);
write<varint>(os, type);
write<Varint>(os, type);
write(os, vh.data(), n * 32);
return result;
}
}
std::array<std::uint8_t, varint_traits<std::size_t>::kMax> vi{};
std::array<std::uint8_t, VarintTraits<std::size_t>::kMax> vi{};
static constexpr std::size_t kCodecType = 1;
auto const vn = writeVarint(vi.data(), kCodecType);
@@ -269,7 +269,7 @@ nodeobjectCompress(void const* in, std::size_t inSize, BufferFactory&& bf)
case 1: // lz4
{
std::uint8_t* p = nullptr;
auto const lzr = NodeStore::lz4Compress(in, inSize, [&p, &vn, &bf](std::size_t n) {
auto const lzr = node_store::lz4Compress(in, inSize, [&p, &vn, &bf](std::size_t n) {
p = reinterpret_cast<std::uint8_t*>(bf(vn + n));
return p + vn;
});
@@ -316,4 +316,4 @@ filterInner(void* in, std::size_t inSize)
}
}
} // namespace xrpl::NodeStore
} // namespace xrpl::node_store

View File

@@ -0,0 +1,163 @@
#pragma once
#include <xrpl/beast/utility/PropertyStream.h>
#include <xrpl/peerfinder/detail/Tuning.h>
#include <cstddef>
#include <cstdint>
#include <optional>
#include <string>
#include <string_view>
namespace xrpl::peer_finder {
struct PeerLimitConfig
{
std::optional<std::size_t> maxPeers;
std::optional<std::size_t> inPeers;
std::optional<std::size_t> outPeers;
};
/**
* PeerFinder configuration settings.
*/
struct Config
{
/**
* The largest number of public peer slots to allow.
* This includes both inbound and outbound, but does not include
* fixed peers.
*/
std::size_t maxPeers{tuning::kDefaultMaxPeers};
/**
* The number of automatic outbound connections to maintain.
* Outbound connections are only maintained if autoConnect
* is `true`.
*/
std::size_t outPeers = calcOutPeers(); // Note: relies on `maxPeers` being initialized
/**
* The number of automatic inbound connections to maintain.
* Inbound connections are only maintained if wantIncoming
* is `true`.
*/
std::size_t inPeers{0};
/**
* `true` if we want our IP address kept private.
*/
bool peerPrivate = true;
/**
* `true` if we want to accept incoming connections.
*/
bool wantIncoming{true};
/**
* `true` if we want to establish connections automatically
*/
bool autoConnect{true};
/**
* The listening port number.
*/
std::uint16_t listeningPort{0};
/**
* The set of features we advertise.
*/
std::string features;
/**
* Limit how many incoming connections we allow per IP
*/
int ipLimit{0};
/**
* `true` if we want to verify endpoints in TMEndpoints messages
*/
bool verifyEndpoints = true;
//--------------------------------------------------------------------------
/**
* Returns a suitable value for outPeers according to the rules.
*/
[[nodiscard]] std::size_t
calcOutPeers() const;
/**
* Adjusts the values so they follow the business rules.
*/
void
applyTuning();
/**
* Write the configuration into a property stream
*/
void
onWrite(beast::PropertyStream::Map& map) const;
/**
* Make peer_finder::Config from peer limit and server mode parameters.
*/
static Config
makeConfig(
bool peerPrivate,
bool standalone,
PeerLimitConfig const& limits,
std::uint16_t port,
bool validationPublicKey,
int ipLimit,
bool verifyEndpoints);
/**
* Compares two configurations for equality field by field.
*/
friend bool
operator==(Config const& lhs, Config const& rhs) = default;
};
//------------------------------------------------------------------------------
/**
* Possible results from activating a slot.
*/
enum class Result { InboundDisabled, DuplicatePeer, IpLimitExceeded, Full, Success };
/**
* @brief Converts a `Result` enum value to its string representation.
*
* This function provides a human-readable string for a given `Result` enum,
* which is useful for logging, debugging, or displaying status messages.
*
* @param result The `Result` enum value to convert.
* @return A `std::string_view` representing the enum value. Returns "unknown"
* if the enum value is not explicitly handled.
*
* @note This function returns a `std::string_view` for performance.
* A `std::string` would need to allocate memory on the heap and copy the
* string literal into it every time the function is called.
*/
inline std::string_view
to_string(Result result) noexcept
{
switch (result)
{
case Result::InboundDisabled:
return "inbound disabled";
case Result::DuplicatePeer:
return "peer already connected";
case Result::IpLimitExceeded:
return "ip limit exceeded";
case Result::Full:
return "slots full";
case Result::Success:
return "success";
}
return "unknown";
}
} // namespace xrpl::peer_finder

View File

@@ -0,0 +1,179 @@
#pragma once
#include <xrpl/beast/net/IPEndpoint.h>
#include <xrpl/beast/utility/PropertyStream.h>
#include <xrpl/peerfinder/Config.h>
#include <xrpl/peerfinder/Slot.h>
#include <xrpl/peerfinder/Types.h>
#include <xrpl/protocol/PublicKey.h>
#include <boost/asio/ip/tcp.hpp>
#include <memory>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
namespace xrpl::peer_finder {
/**
* Maintains a set of IP addresses used for getting into the network.
*/
class Manager : public beast::PropertyStream::Source
{
protected:
Manager() noexcept;
public:
/**
* Destroy the object.
* Any pending source fetch operations are aborted.
* There may be some listener calls made before the
* destructor returns.
*/
~Manager() override = default;
/**
* Set the configuration for the manager.
* The new settings will be applied asynchronously.
* Thread safety:
* Can be called from any threads at any time.
*/
virtual void
setConfig(Config const& config) = 0;
/**
* Transition to the started state, synchronously.
*/
virtual void
start() = 0;
/**
* Transition to the stopped state, synchronously.
*/
virtual void
stop() = 0;
/**
* Returns the configuration for the manager.
*/
virtual Config
config() = 0;
/**
* Add a peer that should always be connected.
* This is useful for maintaining a private cluster of peers.
* The string is the name as specified in the configuration
* file, along with the set of corresponding IP addresses.
*/
virtual void
addFixedPeer(std::string_view name, std::vector<beast::ip::Endpoint> const& addresses) = 0;
/**
* Add a set of strings as fallback ip::Endpoint sources.
* @param name A label used for diagnostics.
*/
virtual void
addFallbackStrings(std::string const& name, std::vector<std::string> const& strings) = 0;
/**
* Add a URL as a fallback location to obtain ip::Endpoint sources.
* @param name A label used for diagnostics.
*/
/* VFALCO NOTE Unimplemented
virtual void addFallbackURL (std::string const& name,
std::string const& url) = 0;
*/
//--------------------------------------------------------------------------
/**
* Create a new inbound slot with the specified remote endpoint.
* If nullptr is returned, then the slot could not be assigned.
* Usually this is because of a detected self-connection.
*/
virtual std::pair<std::shared_ptr<Slot>, Result>
newInboundSlot(
beast::ip::Endpoint const& localEndpoint,
beast::ip::Endpoint const& remoteEndpoint) = 0;
/**
* Create a new outbound slot with the specified remote endpoint.
* If nullptr is returned, then the slot could not be assigned.
* Usually this is because of a duplicate connection.
*/
virtual std::pair<std::shared_ptr<Slot>, Result>
newOutboundSlot(beast::ip::Endpoint const& remoteEndpoint) = 0;
/**
* Called when mtENDPOINTS is received.
*/
virtual void
onEndpoints(std::shared_ptr<Slot> const& slot, Endpoints const& endpoints) = 0;
/**
* Called when the slot is closed.
* This always happens when the socket is closed, unless the socket
* was canceled.
*/
virtual void
onClosed(std::shared_ptr<Slot> const& slot) = 0;
/**
* Called when an outbound connection is deemed to have failed
*/
virtual void
onFailure(std::shared_ptr<Slot> const& slot) = 0;
/**
* Called when we received redirect IPs from a busy peer.
*/
virtual void
onRedirects(
boost::asio::ip::tcp::endpoint const& remoteAddress,
std::vector<boost::asio::ip::tcp::endpoint> const& eps) = 0;
//--------------------------------------------------------------------------
/**
* Called when an outbound connection attempt succeeds.
* The local endpoint must be valid. If the caller receives an error
* when retrieving the local endpoint from the socket, it should
* proceed as if the connection attempt failed by calling on_closed
* instead of on_connected.
* @return `true` if the connection should be kept
*/
virtual bool
onConnected(std::shared_ptr<Slot> const& slot, beast::ip::Endpoint const& localEndpoint) = 0;
/**
* Request an active slot type.
*/
virtual Result
activate(std::shared_ptr<Slot> const& slot, PublicKey const& key, bool reserved) = 0;
/**
* Returns a set of endpoints suitable for redirection.
*/
virtual std::vector<Endpoint>
redirect(std::shared_ptr<Slot> const& slot) = 0;
/**
* Return a set of addresses we should connect to.
*/
virtual std::vector<beast::ip::Endpoint>
autoconnect() = 0;
virtual std::vector<std::pair<std::shared_ptr<Slot>, std::vector<Endpoint>>>
buildEndpointsForPeers() = 0;
/**
* Perform periodic activity.
* This should be called once per second.
*/
virtual void
oncePerSecond() = 0;
};
} // namespace xrpl::peer_finder

View File

@@ -7,7 +7,7 @@
#include <memory>
#include <optional>
namespace xrpl::PeerFinder {
namespace xrpl::peer_finder {
/**
* Properties and state associated with a peer to peer overlay connection.
@@ -52,13 +52,13 @@ public:
/**
* The remote endpoint of socket.
*/
[[nodiscard]] virtual beast::IP::Endpoint const&
[[nodiscard]] virtual beast::ip::Endpoint const&
remoteEndpoint() const = 0;
/**
* The local endpoint of the socket, when known.
*/
[[nodiscard]] virtual std::optional<beast::IP::Endpoint> const&
[[nodiscard]] virtual std::optional<beast::ip::Endpoint> const&
localEndpoint() const = 0;
[[nodiscard]] virtual std::optional<std::uint16_t>
@@ -72,4 +72,4 @@ public:
publicKey() const = 0;
};
} // namespace xrpl::PeerFinder
} // namespace xrpl::peer_finder

View File

@@ -0,0 +1,46 @@
#pragma once
#include <xrpl/beast/clock/abstract_clock.h>
#include <xrpl/beast/net/IPEndpoint.h>
#include <xrpl/peerfinder/detail/Tuning.h>
#include <chrono>
#include <cstdint>
#include <vector>
namespace xrpl::peer_finder {
using clock_type = beast::AbstractClock<std::chrono::steady_clock>;
/**
* Represents a set of addresses.
*/
using IPAddresses = std::vector<beast::ip::Endpoint>;
//------------------------------------------------------------------------------
/**
* Describes a connectable peer address along with some metadata.
*/
struct Endpoint
{
Endpoint() = default;
Endpoint(beast::ip::Endpoint ep, std::uint32_t hops);
std::uint32_t hops = 0;
beast::ip::Endpoint address;
};
inline bool
operator<(Endpoint const& lhs, Endpoint const& rhs)
{
return lhs.address < rhs.address;
}
/**
* A set of Endpoint used for connecting.
*/
using Endpoints = std::vector<Endpoint>;
} // namespace xrpl::peer_finder

View File

@@ -1,11 +1,11 @@
#pragma once
#include <xrpld/peerfinder/PeerfinderManager.h>
#include <xrpld/peerfinder/detail/Store.h>
#include <xrpl/beast/net/IPEndpoint.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/beast/utility/PropertyStream.h>
#include <xrpl/peerfinder/Types.h>
#include <xrpl/peerfinder/detail/Store.h>
#include <xrpl/peerfinder/detail/Tuning.h>
#include <boost/bimap.hpp>
#include <boost/bimap/multiset_of.hpp>
@@ -14,7 +14,7 @@
#include <functional>
namespace xrpl::PeerFinder {
namespace xrpl::peer_finder {
/**
* Stores IP addresses useful for gaining initial connections.
@@ -65,7 +65,7 @@ private:
};
using left_t = boost::bimaps::
unordered_set_of<beast::IP::Endpoint, boost::hash<beast::IP::Endpoint>, std::equal_to<>>;
unordered_set_of<beast::ip::Endpoint, boost::hash<beast::ip::Endpoint>, std::equal_to<>>;
using right_t = boost::bimaps::multiset_of<Entry, std::less<>>;
using map_type = boost::bimap<left_t, right_t>;
using value_type = map_type::value_type;
@@ -73,11 +73,11 @@ private:
struct Transform
{
using first_argument_type = map_type::right_map::const_iterator::value_type const&;
using result_type = beast::IP::Endpoint const&;
using result_type = beast::ip::Endpoint const&;
explicit Transform() = default;
beast::IP::Endpoint const&
beast::ip::Endpoint const&
operator()(map_type::right_map::const_iterator::value_type const& v) const
{
return v.get_left();
@@ -121,7 +121,7 @@ public:
size() const;
/**
* IP::Endpoint iterators that traverse in decreasing valence.
* ip::Endpoint iterators that traverse in decreasing valence.
*/
/** @{ */
[[nodiscard]] const_iterator
@@ -146,25 +146,25 @@ public:
* Add a newly-learned address to the cache.
*/
bool
insert(beast::IP::Endpoint const& endpoint);
insert(beast::ip::Endpoint const& endpoint);
/**
* Add a staticallyconfigured address to the cache.
*/
bool
insertStatic(beast::IP::Endpoint const& endpoint);
insertStatic(beast::ip::Endpoint const& endpoint);
/**
* Called when an outbound connection handshake completes.
*/
void
onSuccess(beast::IP::Endpoint const& endpoint);
onSuccess(beast::ip::Endpoint const& endpoint);
/**
* Called when an outbound connection attempt fails to handshake.
*/
void
onFailure(beast::IP::Endpoint const& endpoint);
onFailure(beast::ip::Endpoint const& endpoint);
/**
* Stores the cache in the persistent database on a timer.
@@ -189,4 +189,4 @@ private:
flagForUpdate();
};
} // namespace xrpl::PeerFinder
} // namespace xrpl::peer_finder

View File

@@ -11,7 +11,7 @@
#include <memory>
#include <mutex>
namespace xrpl::PeerFinder {
namespace xrpl::peer_finder {
/**
* Tests remote listening sockets to make sure they are connectable.
@@ -104,7 +104,7 @@ public:
*/
template <class Handler>
void
asyncConnect(beast::IP::Endpoint const& endpoint, Handler&& handler);
asyncConnect(beast::ip::Endpoint const& endpoint, Handler&& handler);
private:
void
@@ -179,7 +179,7 @@ Checker<Protocol>::wait()
template <class Protocol>
template <class Handler>
void
Checker<Protocol>::asyncConnect(beast::IP::Endpoint const& endpoint, Handler&& handler)
Checker<Protocol>::asyncConnect(beast::ip::Endpoint const& endpoint, Handler&& handler)
{
auto const op =
std::make_shared<AsyncOp<Handler>>(*this, ioContext_, std::forward<Handler>(handler));
@@ -202,4 +202,4 @@ Checker<Protocol>::remove(BasicAsyncOp& op)
cond_.notify_all();
}
} // namespace xrpl::PeerFinder
} // namespace xrpl::peer_finder

View File

@@ -1,17 +1,16 @@
#pragma once
#include <xrpld/peerfinder/PeerfinderManager.h>
#include <xrpld/peerfinder/Slot.h>
#include <xrpld/peerfinder/detail/Tuning.h>
#include <xrpl/beast/utility/PropertyStream.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/peerfinder/Config.h>
#include <xrpl/peerfinder/Slot.h>
#include <xrpl/peerfinder/detail/Tuning.h>
#include <cstddef>
#include <sstream>
#include <string>
namespace xrpl::PeerFinder {
namespace xrpl::peer_finder {
/**
* Direction of a slot count adjustment.
@@ -51,7 +50,7 @@ public:
// Must be handshaked and in the right state
XRPL_ASSERT(
s.state() == Slot::State::Connected || s.state() == Slot::State::Accept,
"xrpl::PeerFinder::Counts::can_activate : valid input state");
"xrpl::peer_finder::Counts::can_activate : valid input state");
if (s.fixed() || s.reserved())
return true;
@@ -68,9 +67,9 @@ public:
[[nodiscard]] std::size_t
attemptsNeeded() const
{
if (attempts_ >= Tuning::kMaxConnectAttempts)
if (attempts_ >= tuning::kMaxConnectAttempts)
return 0;
return Tuning::kMaxConnectAttempts - attempts_;
return tuning::kMaxConnectAttempts - attempts_;
}
/**
@@ -296,7 +295,7 @@ private:
switch (s.state())
{
case Slot::State::Accept:
XRPL_ASSERT(s.inbound(), "xrpl::PeerFinder::Counts::adjust : input is inbound");
XRPL_ASSERT(s.inbound(), "xrpl::peer_finder::Counts::adjust : input is inbound");
acceptCount_ += n;
break;
@@ -304,7 +303,7 @@ private:
case Slot::State::Connected:
XRPL_ASSERT(
!s.inbound(),
"xrpl::PeerFinder::Counts::adjust : input is not "
"xrpl::peer_finder::Counts::adjust : input is not "
"inbound");
attempts_ += n;
break;
@@ -332,7 +331,7 @@ private:
// LCOV_EXCL_START
default:
UNREACHABLE("xrpl::PeerFinder::Counts::adjust : invalid input state");
UNREACHABLE("xrpl::peer_finder::Counts::adjust : invalid input state");
break;
// LCOV_EXCL_STOP
};
@@ -392,4 +391,4 @@ private:
int closingCount_{0};
};
} // namespace xrpl::PeerFinder
} // namespace xrpl::peer_finder

View File

@@ -1,13 +1,13 @@
#pragma once
#include <xrpld/peerfinder/PeerfinderManager.h>
#include <xrpld/peerfinder/detail/Tuning.h>
#include <xrpl/peerfinder/Types.h>
#include <xrpl/peerfinder/detail/Tuning.h>
#include <algorithm>
#include <chrono>
#include <cstddef>
namespace xrpl::PeerFinder {
namespace xrpl::peer_finder {
/**
* Metadata for a Fixed slot.
@@ -36,8 +36,8 @@ public:
void
failure(clock_type::time_point const& now)
{
failures_ = std::min(failures_ + 1, Tuning::kConnectionBackoff.size() - 1);
when_ = now + std::chrono::minutes(Tuning::kConnectionBackoff[failures_]);
failures_ = std::min(failures_ + 1, tuning::kConnectionBackoff.size() - 1);
when_ = now + std::chrono::minutes(tuning::kConnectionBackoff[failures_]);
}
/**
@@ -55,4 +55,4 @@ private:
std::size_t failures_{0};
};
} // namespace xrpl::PeerFinder
} // namespace xrpl::peer_finder

View File

@@ -1,19 +1,18 @@
#pragma once
#include <xrpld/peerfinder/PeerfinderManager.h>
#include <xrpld/peerfinder/detail/SlotImp.h>
#include <xrpld/peerfinder/detail/Tuning.h>
#include <xrpl/beast/container/aged_set.h>
#include <xrpl/beast/net/IPAddress.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/peerfinder/Types.h>
#include <xrpl/peerfinder/detail/SlotImp.h>
#include <xrpl/peerfinder/detail/Tuning.h>
#include <algorithm>
#include <cstddef>
#include <utility>
#include <vector>
namespace xrpl::PeerFinder {
namespace xrpl::peer_finder {
namespace detail {
@@ -29,7 +28,7 @@ template <class Target, class HopContainer>
std::size_t
handoutOne(Target& t, HopContainer& h)
{
XRPL_ASSERT(!t.full(), "xrpl::PeerFinder::detail::handoutOne : target is not full");
XRPL_ASSERT(!t.full(), "xrpl::peer_finder::detail::handoutOne : target is not full");
for (auto it = h.begin(); it != h.end(); ++it)
{
auto const& e = *it;
@@ -96,7 +95,7 @@ public:
[[nodiscard]] bool
full() const
{
return list_.size() >= Tuning::kRedirectEndpointCount;
return list_.size() >= tuning::kRedirectEndpointCount;
}
[[nodiscard]] SlotImp::ptr const&
@@ -125,7 +124,7 @@ private:
template <class>
RedirectHandouts::RedirectHandouts(SlotImp::ptr slot) : slot_(std::move(slot))
{
list_.reserve(Tuning::kRedirectEndpointCount);
list_.reserve(tuning::kRedirectEndpointCount);
}
template <class>
@@ -139,7 +138,7 @@ RedirectHandouts::tryInsert(Endpoint const& ep)
// addresses in a peer HTTP handshake instead of
// the tmENDPOINTS message.
//
if (ep.hops > Tuning::kMaxHops)
if (ep.hops > tuning::kMaxHops)
return false;
// Don't send them our address
@@ -182,7 +181,7 @@ public:
[[nodiscard]] bool
full() const
{
return list_.size() >= Tuning::kNumberOfEndpoints;
return list_.size() >= tuning::kNumberOfEndpoints;
}
void
@@ -211,7 +210,7 @@ private:
template <class>
SlotHandouts::SlotHandouts(SlotImp::ptr slot) : slot_(std::move(slot))
{
list_.reserve(Tuning::kNumberOfEndpoints);
list_.reserve(tuning::kNumberOfEndpoints);
}
template <class>
@@ -221,7 +220,7 @@ SlotHandouts::tryInsert(Endpoint const& ep)
if (full())
return false;
if (ep.hops > Tuning::kMaxHops)
if (ep.hops > tuning::kMaxHops)
return false;
if (slot_->recent.filter(ep.address, ep.hops))
@@ -260,9 +259,9 @@ class ConnectHandouts
public:
// Keeps track of addresses we have made outgoing connections
// to, for the purposes of not connecting to them too frequently.
using Squelches = beast::aged_set<beast::IP::Address>;
using Squelches = beast::aged_set<beast::ip::Address>;
using list_type = std::vector<beast::IP::Endpoint>;
using list_type = std::vector<beast::ip::Endpoint>;
private:
std::size_t needed_;
@@ -275,7 +274,7 @@ public:
template <class = void>
bool
tryInsert(beast::IP::Endpoint const& endpoint);
tryInsert(beast::ip::Endpoint const& endpoint);
[[nodiscard]] bool
empty() const
@@ -317,13 +316,13 @@ ConnectHandouts::ConnectHandouts(std::size_t needed, Squelches& squelches)
template <class>
bool
ConnectHandouts::tryInsert(beast::IP::Endpoint const& endpoint)
ConnectHandouts::tryInsert(beast::ip::Endpoint const& endpoint)
{
if (full())
return false;
// Make sure the address isn't already in our list
if (std::ranges::any_of(list_, [&endpoint](beast::IP::Endpoint const& other) {
if (std::ranges::any_of(list_, [&endpoint](beast::ip::Endpoint const& other) {
// Ignore port for security reasons
return other.address() == endpoint.address();
}))
@@ -342,4 +341,4 @@ ConnectHandouts::tryInsert(beast::IP::Endpoint const& endpoint)
return true;
}
} // namespace xrpl::PeerFinder
} // namespace xrpl::peer_finder

View File

@@ -1,9 +1,5 @@
#pragma once
#include <xrpld/peerfinder/PeerfinderManager.h>
#include <xrpld/peerfinder/detail/Tuning.h>
#include <xrpld/peerfinder/detail/iosformat.h>
#include <xrpl/basics/Log.h>
#include <xrpl/basics/random.h>
#include <xrpl/beast/container/aged_map.h>
@@ -12,6 +8,8 @@
#include <xrpl/beast/utility/PropertyStream.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/beast/utility/maybe_const.h>
#include <xrpl/peerfinder/Types.h>
#include <xrpl/peerfinder/detail/Tuning.h>
#include <boost/intrusive/list.hpp>
#include <boost/iterator/transform_iterator.hpp>
@@ -22,6 +20,8 @@
#include <cstddef>
#include <cstdint>
#include <functional>
#include <iomanip>
#include <ios>
#include <iterator>
#include <memory>
#include <sstream>
@@ -29,7 +29,7 @@
#include <utility>
#include <vector>
namespace xrpl::PeerFinder {
namespace xrpl::peer_finder {
template <class>
class Livecache;
@@ -188,10 +188,10 @@ class Livecache : protected detail::LivecacheBase
{
private:
using cache_type = beast::aged_map<
beast::IP::Endpoint,
beast::ip::Endpoint,
Element,
std::chrono::steady_clock,
std::less<beast::IP::Endpoint>,
std::less<beast::ip::Endpoint>,
Allocator>;
beast::Journal journal_;
@@ -220,8 +220,8 @@ public:
// but not given out (since they would exceed maxHops). They
// are used for automatic connection attempts.
//
using Histogram = std::array<int, 1 + Tuning::kMaxHops + 1>;
using lists_type = std::array<list_type, 1 + Tuning::kMaxHops + 1>;
using Histogram = std::array<int, 1 + tuning::kMaxHops + 1>;
using lists_type = std::array<list_type, 1 + tuning::kMaxHops + 1>;
template <bool IsConst>
struct Transform
@@ -400,7 +400,7 @@ Livecache<Allocator>::expire()
{
std::size_t n(0);
typename cache_type::time_point const expired(
cache_.clock().now() - Tuning::kLiveCacheSecondsToLive);
cache_.clock().now() - tuning::kLiveCacheSecondsToLive);
for (auto iter(cache_.chronological.begin());
iter != cache_.chronological.end() && iter.when() <= expired;)
{
@@ -411,7 +411,7 @@ Livecache<Allocator>::expire()
}
if (n > 0)
{
JLOG(journal_.debug()) << beast::Leftw(18) << "Livecache expired " << n
JLOG(journal_.debug()) << std::left << std::setw(18) << "Livecache expired " << n
<< ((n > 1) ? " entries" : " entry");
}
}
@@ -427,14 +427,14 @@ Livecache<Allocator>::insert(Endpoint const& ep)
// when redirecting.
//
XRPL_ASSERT(
ep.hops <= (Tuning::kMaxHops + 1),
"xrpl::PeerFinder::Livecache::insert : maximum input hops");
ep.hops <= (tuning::kMaxHops + 1),
"xrpl::peer_finder::Livecache::insert : maximum input hops");
auto result = cache_.emplace(ep.address, ep);
Element& e(result.first->second);
if (result.second)
{
hops.insert(e);
JLOG(journal_.debug()) << beast::Leftw(18) << "Livecache insert " << ep.address
JLOG(journal_.debug()) << std::left << std::setw(18) << "Livecache insert " << ep.address
<< " at hops " << ep.hops;
return;
}
@@ -442,7 +442,7 @@ Livecache<Allocator>::insert(Endpoint const& ep)
{
// Drop duplicates at higher hops
std::size_t const excess(ep.hops - e.endpoint.hops);
JLOG(journal_.trace()) << beast::Leftw(18) << "Livecache drop " << ep.address
JLOG(journal_.trace()) << std::left << std::setw(18) << "Livecache drop " << ep.address
<< " at hops +" << excess;
return;
}
@@ -453,12 +453,12 @@ Livecache<Allocator>::insert(Endpoint const& ep)
if (ep.hops < e.endpoint.hops)
{
hops.reinsert(e, ep.hops);
JLOG(journal_.debug()) << beast::Leftw(18) << "Livecache update " << ep.address
JLOG(journal_.debug()) << std::left << std::setw(18) << "Livecache update " << ep.address
<< " at hops " << ep.hops;
}
else
{
JLOG(journal_.trace()) << beast::Leftw(18) << "Livecache refresh " << ep.address
JLOG(journal_.trace()) << std::left << std::setw(18) << "Livecache refresh " << ep.address
<< " at hops " << ep.hops;
}
}
@@ -468,7 +468,7 @@ void
Livecache<Allocator>::onWrite(beast::PropertyStream::Map& map)
{
typename cache_type::time_point const expired(
cache_.clock().now() - Tuning::kLiveCacheSecondsToLive);
cache_.clock().now() - tuning::kLiveCacheSecondsToLive);
map["size"] = size();
map["hist"] = hops.histogram();
beast::PropertyStream::Set set("entries", map);
@@ -527,8 +527,8 @@ void
Livecache<Allocator>::HopsT::insert(Element& e)
{
XRPL_ASSERT(
e.endpoint.hops <= Tuning::kMaxHops + 1,
"xrpl::PeerFinder::Livecache::HopsT::insert : maximum input hops");
e.endpoint.hops <= tuning::kMaxHops + 1,
"xrpl::peer_finder::Livecache::HopsT::insert : maximum input hops");
// This has security implications without a shuffle
lists_[e.endpoint.hops].push_front(e);
++hist_[e.endpoint.hops];
@@ -539,8 +539,8 @@ void
Livecache<Allocator>::HopsT::reinsert(Element& e, std::uint32_t numHops)
{
XRPL_ASSERT(
numHops <= Tuning::kMaxHops + 1,
"xrpl::PeerFinder::Livecache::HopsT::reinsert : maximum hops input");
numHops <= tuning::kMaxHops + 1,
"xrpl::peer_finder::Livecache::HopsT::reinsert : maximum hops input");
auto& list = lists_[e.endpoint.hops];
list.erase(list.iterator_to(e));
@@ -561,4 +561,4 @@ Livecache<Allocator>::HopsT::remove(Element& e)
list.erase(list.iterator_to(e));
}
} // namespace xrpl::PeerFinder
} // namespace xrpl::peer_finder

View File

@@ -1,17 +1,5 @@
#pragma once
#include <xrpld/peerfinder/PeerfinderManager.h>
#include <xrpld/peerfinder/Slot.h>
#include <xrpld/peerfinder/detail/Bootcache.h>
#include <xrpld/peerfinder/detail/Counts.h>
#include <xrpld/peerfinder/detail/Fixed.h>
#include <xrpld/peerfinder/detail/Handouts.h>
#include <xrpld/peerfinder/detail/Livecache.h>
#include <xrpld/peerfinder/detail/SlotImp.h>
#include <xrpld/peerfinder/detail/Source.h>
#include <xrpld/peerfinder/detail/Store.h>
#include <xrpld/peerfinder/detail/iosformat.h>
#include <xrpl/basics/Log.h>
#include <xrpl/basics/contract.h>
#include <xrpl/basics/random.h>
@@ -22,24 +10,40 @@
#include <xrpl/beast/utility/PropertyStream.h>
#include <xrpl/beast/utility/WrappedSink.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/peerfinder/Config.h>
#include <xrpl/peerfinder/Slot.h>
#include <xrpl/peerfinder/Types.h>
#include <xrpl/peerfinder/detail/Bootcache.h>
#include <xrpl/peerfinder/detail/Counts.h>
#include <xrpl/peerfinder/detail/Fixed.h>
#include <xrpl/peerfinder/detail/Handouts.h>
#include <xrpl/peerfinder/detail/Livecache.h>
#include <xrpl/peerfinder/detail/SlotImp.h>
#include <xrpl/peerfinder/detail/Source.h>
#include <xrpl/peerfinder/detail/Store.h>
#include <xrpl/protocol/PublicKey.h>
#include <boost/asio/error.hpp>
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <iomanip>
#include <ios>
#include <map>
#include <memory>
#include <mutex>
#include <optional>
#include <set>
#include <stdexcept>
#include <string>
#include <string_view>
#include <tuple>
#include <utility>
#include <vector>
namespace xrpl::PeerFinder {
namespace xrpl::peer_finder {
/**
* The Logic for maintaining the list of Slot addresses.
@@ -53,7 +57,7 @@ public:
// Maps remote endpoints to slots. Since a slot has a
// remote endpoint upon construction, this holds all counts_.
//
using Slots = std::map<beast::IP::Endpoint, std::shared_ptr<SlotImp>>;
using Slots = std::map<beast::ip::Endpoint, std::shared_ptr<SlotImp>>;
beast::Journal journal;
clock_type& clock;
@@ -77,7 +81,7 @@ private:
Counts counts_;
// A list of slots that should always be connected
std::map<beast::IP::Endpoint, Fixed> fixed_;
std::map<beast::ip::Endpoint, Fixed> fixed_;
public:
// Live livecache from mtENDPOINTS messages
@@ -92,7 +96,7 @@ public:
// The addresses (but not port) we are connected to. This includes
// outgoing connection attempts. Note that this set can contain
// duplicates (since the port is not set)
std::multiset<beast::IP::Address> connectedAddresses;
std::multiset<beast::ip::Address> connectedAddresses;
// Set of public keys belonging to active peers
std::set<PublicKey> keys;
@@ -166,13 +170,13 @@ public:
}
void
addFixedPeer(std::string_view name, beast::IP::Endpoint const& ep)
addFixedPeer(std::string_view name, beast::ip::Endpoint const& ep)
{
addFixedPeer(name, std::vector<beast::IP::Endpoint>{ep});
addFixedPeer(name, std::vector<beast::ip::Endpoint>{ep});
}
void
addFixedPeer(std::string_view name, std::vector<beast::IP::Endpoint> const& addresses)
addFixedPeer(std::string_view name, std::vector<beast::ip::Endpoint> const& addresses)
{
std::scoped_lock const _(lock);
@@ -197,8 +201,8 @@ public:
if (result.second)
{
JLOG(journal.debug())
<< beast::Leftw(18) << "Logic add fixed '" << name << "' at " << remoteAddress;
JLOG(journal.debug()) << std::left << std::setw(18) << "Logic add fixed '" << name
<< "' at " << remoteAddress;
return;
}
}
@@ -209,8 +213,8 @@ public:
// Called when the Checker completes a connectivity test
void
checkComplete(
beast::IP::Endpoint const& remoteAddress,
beast::IP::Endpoint const& checkedAddress,
beast::ip::Endpoint const& remoteAddress,
beast::ip::Endpoint const& checkedAddress,
boost::system::error_code ec)
{
if (ec == boost::asio::error::operation_aborted)
@@ -221,7 +225,7 @@ public:
if (iter == slots.end())
{
// The slot disconnected before we finished the check
JLOG(journal.debug()) << beast::Leftw(18) << "Logic tested " << checkedAddress
JLOG(journal.debug()) << std::left << std::setw(18) << "Logic tested " << checkedAddress
<< " but the connection was closed";
return;
}
@@ -252,10 +256,10 @@ public:
std::pair<SlotImp::ptr, Result>
newInboundSlot(
beast::IP::Endpoint const& localEndpoint,
beast::IP::Endpoint const& remoteEndpoint)
beast::ip::Endpoint const& localEndpoint,
beast::ip::Endpoint const& remoteEndpoint)
{
JLOG(journal.debug()) << beast::Leftw(18) << "Logic accept" << remoteEndpoint
JLOG(journal.debug()) << std::left << std::setw(18) << "Logic accept" << remoteEndpoint
<< " on local " << localEndpoint;
std::scoped_lock const _(lock);
@@ -266,7 +270,7 @@ public:
auto const count = connectedAddresses.count(remoteEndpoint.address());
if (count + 1 > config_.ipLimit)
{
JLOG(journal.debug()) << beast::Leftw(18) << "Logic dropping inbound "
JLOG(journal.debug()) << std::left << std::setw(18) << "Logic dropping inbound "
<< remoteEndpoint << " because of ip limits.";
return {SlotImp::ptr(), Result::IpLimitExceeded};
}
@@ -275,8 +279,8 @@ public:
// Check for duplicate connection
if (slots.contains(remoteEndpoint))
{
JLOG(journal.debug()) << beast::Leftw(18) << "Logic dropping " << remoteEndpoint
<< " as duplicate incoming";
JLOG(journal.debug()) << std::left << std::setw(18) << "Logic dropping "
<< remoteEndpoint << " as duplicate incoming";
return {SlotImp::ptr(), Result::DuplicatePeer};
}
@@ -289,7 +293,7 @@ public:
// Remote address must not already exist
XRPL_ASSERT(
result.second,
"xrpl::PeerFinder::Logic::new_inbound_slot : remote endpoint "
"xrpl::peer_finder::Logic::new_inbound_slot : remote endpoint "
"inserted");
// Add to the connected address list
connectedAddresses.emplace(remoteEndpoint.address());
@@ -302,17 +306,17 @@ public:
// Can't check for self-connect because we don't know the local endpoint
std::pair<SlotImp::ptr, Result>
newOutboundSlot(beast::IP::Endpoint const& remoteEndpoint)
newOutboundSlot(beast::ip::Endpoint const& remoteEndpoint)
{
JLOG(journal.debug()) << beast::Leftw(18) << "Logic connect " << remoteEndpoint;
JLOG(journal.debug()) << std::left << std::setw(18) << "Logic connect " << remoteEndpoint;
std::scoped_lock const _(lock);
// Check for duplicate connection
if (slots.contains(remoteEndpoint))
{
JLOG(journal.debug()) << beast::Leftw(18) << "Logic dropping " << remoteEndpoint
<< " as duplicate connect";
JLOG(journal.debug()) << std::left << std::setw(18) << "Logic dropping "
<< remoteEndpoint << " as duplicate connect";
return {SlotImp::ptr(), Result::DuplicatePeer};
}
@@ -325,7 +329,7 @@ public:
// Remote address must not already exist
XRPL_ASSERT(
result.second,
"xrpl::PeerFinder::Logic::new_outbound_slot : remote endpoint "
"xrpl::peer_finder::Logic::new_outbound_slot : remote endpoint "
"inserted");
// Add to the connected address list
@@ -338,7 +342,7 @@ public:
}
bool
onConnected(SlotImp::ptr const& slot, beast::IP::Endpoint const& localEndpoint)
onConnected(SlotImp::ptr const& slot, beast::ip::Endpoint const& localEndpoint)
{
beast::WrappedSink sink{journal.sink(), slot->prefix()};
beast::Journal const journal{sink};
@@ -350,7 +354,7 @@ public:
// The object must exist in our table
XRPL_ASSERT(
slots.contains(slot->remoteEndpoint()),
"xrpl::PeerFinder::Logic::onConnected : valid slot input");
"xrpl::peer_finder::Logic::onConnected : valid slot input");
// Assign the local endpoint now that it's known
slot->localEndpoint(localEndpoint);
@@ -361,7 +365,7 @@ public:
{
XRPL_ASSERT(
iter->second->localEndpoint() == slot->remoteEndpoint(),
"xrpl::PeerFinder::Logic::onConnected : local and remote "
"xrpl::peer_finder::Logic::onConnected : local and remote "
"endpoints do match");
JLOG(journal.warn()) << "Logic dropping as self connect";
return false;
@@ -389,11 +393,11 @@ public:
// The object must exist in our table
XRPL_ASSERT(
slots.contains(slot->remoteEndpoint()),
"xrpl::PeerFinder::Logic::activate : valid slot input");
"xrpl::peer_finder::Logic::activate : valid slot input");
// Must be accepted or connected
XRPL_ASSERT(
slot->state() == Slot::State::Accept || slot->state() == Slot::State::Connected,
"xrpl::PeerFinder::Logic::activate : valid slot state");
"xrpl::peer_finder::Logic::activate : valid slot state");
// Check for duplicate connection by key
if (keys.contains(key))
@@ -421,7 +425,7 @@ public:
{
[[maybe_unused]] bool const inserted = keys.insert(key).second;
// Public key must not already exist
XRPL_ASSERT(inserted, "xrpl::PeerFinder::Logic::activate : public key inserted");
XRPL_ASSERT(inserted, "xrpl::peer_finder::Logic::activate : public key inserted");
}
// Change state and update counts
@@ -439,7 +443,7 @@ public:
if (iter == fixed_.end())
{
logicError(
"PeerFinder::Logic::activate(): remote_endpoint "
"peer_finder::Logic::activate(): remote_endpoint "
"missing from fixed_");
}
@@ -472,10 +476,10 @@ public:
// VFALCO TODO This should add the returned addresses to the
// squelch list in one go once the list is built,
// rather than having each module add to the squelch list.
std::vector<beast::IP::Endpoint>
std::vector<beast::ip::Endpoint>
autoconnect()
{
std::vector<beast::IP::Endpoint> none;
std::vector<beast::ip::Endpoint> none;
std::scoped_lock const _(lock);
@@ -506,15 +510,15 @@ public:
if (!h.list().empty())
{
JLOG(journal.debug())
<< beast::Leftw(18) << "Logic connect " << h.list().size() << " fixed";
JLOG(journal.debug()) << std::left << std::setw(18) << "Logic connect "
<< h.list().size() << " fixed";
return h.list();
}
if (counts_.attempts() > 0)
{
JLOG(journal.debug())
<< beast::Leftw(18) << "Logic waiting on " << counts_.attempts() << " attempts";
JLOG(journal.debug()) << std::left << std::setw(18) << "Logic waiting on "
<< counts_.attempts() << " attempts";
return none;
}
}
@@ -535,14 +539,14 @@ public:
if (!h.list().empty())
{
JLOG(journal.debug())
<< beast::Leftw(18) << "Logic connect " << h.list().size() << " live "
<< std::left << std::setw(18) << "Logic connect " << h.list().size() << " live "
<< ((h.list().size() > 1) ? "endpoints" : "endpoint");
return h.list();
}
if (counts_.attempts() > 0)
{
JLOG(journal.debug())
<< beast::Leftw(18) << "Logic waiting on " << counts_.attempts() << " attempts";
JLOG(journal.debug()) << std::left << std::setw(18) << "Logic waiting on "
<< counts_.attempts() << " attempts";
return none;
}
}
@@ -568,8 +572,9 @@ public:
if (!h.list().empty())
{
JLOG(journal.debug()) << beast::Leftw(18) << "Logic connect " << h.list().size()
<< " boot " << ((h.list().size() > 1) ? "addresses" : "address");
JLOG(journal.debug()) << std::left << std::setw(18) << "Logic connect "
<< h.list().size() << " boot "
<< ((h.list().size() > 1) ? "addresses" : "address");
return h.list();
}
@@ -630,7 +635,7 @@ public:
// either. ipv6 has a slightly more compact string
// representation of 0, so use that for self entries.
ep.address =
beast::IP::Endpoint(beast::IP::AddressV6()).atPort(config_.listeningPort);
beast::ip::Endpoint(beast::ip::AddressV6()).atPort(config_.listeningPort);
for (auto& t : targets)
t.insert(ep);
}
@@ -651,7 +656,7 @@ public:
result.emplace_back(slot, list);
}
whenBroadcast = now + Tuning::kSecondsPerMessage;
whenBroadcast = now + tuning::kSecondsPerMessage;
}
return result;
@@ -670,7 +675,7 @@ public:
entry.second->expire();
// Expire the recent attempts table
beast::expire(squelches, Tuning::kRecentAttemptDuration);
beast::expire(squelches, tuning::kRecentAttemptDuration);
bootcache.periodicActivity();
}
@@ -687,10 +692,10 @@ public:
Endpoint& ep(*iter);
// Enforce hop limit
if (ep.hops > Tuning::kMaxHops)
if (ep.hops > tuning::kMaxHops)
{
JLOG(journal.debug()) << beast::Leftw(18) << "Endpoints drop " << ep.address
<< " for excess hops " << ep.hops;
JLOG(journal.debug()) << std::left << std::setw(18) << "Endpoints drop "
<< ep.address << " for excess hops " << ep.hops;
iter = list.erase(iter);
continue;
}
@@ -706,18 +711,18 @@ public:
}
else
{
JLOG(journal.debug())
<< beast::Leftw(18) << "Endpoints drop " << ep.address << " for extra self";
JLOG(journal.debug()) << std::left << std::setw(18) << "Endpoints drop "
<< ep.address << " for extra self";
iter = list.erase(iter);
continue;
}
}
// Discard invalid addresses
if (config_.verifyEndpoints && !isValidAddress(ep.address))
if (!isValidAddress(ep.address))
{
JLOG(journal.debug())
<< beast::Leftw(18) << "Endpoints drop " << ep.address << " as invalid";
JLOG(journal.debug()) << std::left << std::setw(18) << "Endpoints drop "
<< ep.address << " as invalid";
iter = list.erase(iter);
continue;
}
@@ -727,8 +732,8 @@ public:
return ep.address == other.address;
}))
{
JLOG(journal.debug())
<< beast::Leftw(18) << "Endpoints drop " << ep.address << " as duplicate";
JLOG(journal.debug()) << std::left << std::setw(18) << "Endpoints drop "
<< ep.address << " as duplicate";
iter = list.erase(iter);
continue;
}
@@ -749,10 +754,10 @@ public:
beast::Journal const journal{sink};
// If we're sent too many endpoints, sample them at random:
if (list.size() > Tuning::kNumberOfEndpointsMax)
if (list.size() > tuning::kNumberOfEndpointsMax)
{
std::shuffle(list.begin(), list.end(), defaultPrng());
list.resize(Tuning::kNumberOfEndpointsMax);
list.resize(tuning::kNumberOfEndpointsMax);
}
JLOG(journal.trace()) << "Endpoints contained " << list.size()
@@ -763,12 +768,12 @@ public:
// The object must exist in our table
XRPL_ASSERT(
slots.contains(slot->remoteEndpoint()),
"xrpl::PeerFinder::Logic::onEndpoints : valid slot input");
"xrpl::peer_finder::Logic::onEndpoints : valid slot input");
// Must be handshaked!
XRPL_ASSERT(
slot->state() == Slot::State::Active,
"xrpl::PeerFinder::Logic::onEndpoints : valid slot state");
"xrpl::peer_finder::Logic::onEndpoints : valid slot state");
clock_type::time_point const now(clock.now());
@@ -780,7 +785,7 @@ public:
for (auto const& ep : list)
{
XRPL_ASSERT(ep.hops, "xrpl::PeerFinder::Logic::onEndpoints : nonzero hops");
XRPL_ASSERT(ep.hops, "xrpl::peer_finder::Logic::onEndpoints : nonzero hops");
slot->recent.insert(ep.address, ep.hops);
@@ -832,7 +837,7 @@ public:
bootcache.insert(ep.address);
}
slot->whenAcceptEndpoints = now + Tuning::kSecondsPerMessage;
slot->whenAcceptEndpoints = now + tuning::kSecondsPerMessage;
}
//--------------------------------------------------------------------------
@@ -846,7 +851,7 @@ public:
if (iter == slots.end())
{
logicError(
"PeerFinder::Logic::remove(): remote_endpoint "
"peer_finder::Logic::remove(): remote_endpoint "
"missing from slots_");
}
@@ -861,7 +866,7 @@ public:
if (iter == keys.end())
{
logicError(
"PeerFinder::Logic::remove(): public_key missing "
"peer_finder::Logic::remove(): public_key missing "
"from keys_");
}
@@ -874,7 +879,7 @@ public:
if (iter == connectedAddresses.end())
{
logicError(
"PeerFinder::Logic::remove(): remote_endpoint "
"peer_finder::Logic::remove(): remote_endpoint "
"address missing from connectedAddresses_");
}
@@ -902,7 +907,7 @@ public:
if (iter == fixed_.end())
{
logicError(
"PeerFinder::Logic::on_closed(): remote_endpoint "
"peer_finder::Logic::on_closed(): remote_endpoint "
"missing from fixed_");
}
@@ -938,7 +943,7 @@ public:
// LCOV_EXCL_START
default:
UNREACHABLE(
"xrpl::PeerFinder::Logic::on_closed : invalid slot "
"xrpl::peer_finder::Logic::on_closed : invalid slot "
"state");
break;
// LCOV_EXCL_STOP
@@ -963,17 +968,17 @@ public:
// Returns `true` if the address matches a fixed slot address
// Must have the lock held
bool
fixed(beast::IP::Endpoint const& endpoint) const
fixed(beast::ip::Endpoint const& endpoint) const
{
return std::ranges::any_of(
fixed_, [&endpoint](auto const& entry) { return entry.first == endpoint; });
}
// Returns `true` if the address matches a fixed slot address
// Note that this does not use the port information in the IP::Endpoint
// Note that this does not use the port information in the ip::Endpoint
// Must have the lock held
bool
fixed(beast::IP::Address const& address) const
fixed(beast::ip::Address const& address) const
{
return std::ranges::any_of(
fixed_, [&address](auto const& entry) { return entry.first.address() == address; });
@@ -1074,13 +1079,13 @@ public:
if (!results.error)
{
int const count(addBootcacheAddresses(results.addresses));
JLOG(journal.info()) << beast::Leftw(18) << "Logic added " << count << " new "
JLOG(journal.info()) << std::left << std::setw(18) << "Logic added " << count << " new "
<< ((count == 1) ? "address" : "addresses") << " from "
<< source->name();
}
else
{
JLOG(journal.error()) << beast::Leftw(18) << "Logic failed "
JLOG(journal.error()) << std::left << std::setw(18) << "Logic failed "
<< "'" << source->name() << "' fetch, "
<< results.error.message();
}
@@ -1092,14 +1097,12 @@ public:
//
//--------------------------------------------------------------------------
// Returns true if the IP::Endpoint contains no invalid data.
// Returns true if the ip::Endpoint contains no invalid data.
bool
isValidAddress(beast::IP::Endpoint const& address)
isValidAddress(beast::ip::Endpoint const& address)
{
if (isUnspecified(address))
return false;
if (isLoopback(address))
return false;
if (!isPublic(address))
return false;
if (address.port() == 0)
@@ -1217,13 +1220,13 @@ Logic<Checker>::onRedirects(
{
std::scoped_lock const _(lock);
std::size_t n = 0;
for (; first != last && n < Tuning::kMaxRedirects; ++first, ++n)
for (; first != last && n < tuning::kMaxRedirects; ++first, ++n)
bootcache.insert(beast::IPAddressConversion::fromAsio(*first));
if (n > 0)
{
JLOG(journal.trace()) << beast::Leftw(18) << "Logic add " << n << " redirect IPs from "
<< remoteAddress;
JLOG(journal.trace()) << std::left << std::setw(18) << "Logic add " << n
<< " redirect IPs from " << remoteAddress;
}
}
} // namespace xrpl::PeerFinder
} // namespace xrpl::peer_finder

View File

@@ -1,10 +1,9 @@
#pragma once
#include <xrpld/peerfinder/PeerfinderManager.h>
#include <xrpld/peerfinder/Slot.h>
#include <xrpl/beast/container/aged_unordered_map.h>
#include <xrpl/beast/net/IPEndpoint.h>
#include <xrpl/peerfinder/Slot.h>
#include <xrpl/peerfinder/Types.h>
#include <xrpl/protocol/PublicKey.h>
#include <atomic>
@@ -13,7 +12,7 @@
#include <optional>
#include <string>
namespace xrpl::PeerFinder {
namespace xrpl::peer_finder {
class SlotImp : public Slot
{
@@ -22,13 +21,13 @@ public:
// inbound
SlotImp(
beast::IP::Endpoint const& localEndpoint,
beast::IP::Endpoint remoteEndpoint,
beast::ip::Endpoint const& localEndpoint,
beast::ip::Endpoint remoteEndpoint,
bool fixed,
clock_type& clock);
// outbound
SlotImp(beast::IP::Endpoint remoteEndpoint, bool fixed, clock_type& clock);
SlotImp(beast::ip::Endpoint remoteEndpoint, bool fixed, clock_type& clock);
bool
inbound() const override
@@ -54,13 +53,13 @@ public:
return state_;
}
beast::IP::Endpoint const&
beast::ip::Endpoint const&
remoteEndpoint() const override
{
return remoteEndpoint_;
}
std::optional<beast::IP::Endpoint> const&
std::optional<beast::ip::Endpoint> const&
localEndpoint() const override
{
return localEndpoint_;
@@ -94,13 +93,13 @@ public:
}
void
localEndpoint(beast::IP::Endpoint const& endpoint)
localEndpoint(beast::ip::Endpoint const& endpoint)
{
localEndpoint_ = endpoint;
}
void
remoteEndpoint(beast::IP::Endpoint const& endpoint)
remoteEndpoint(beast::ip::Endpoint const& endpoint)
{
remoteEndpoint_ = endpoint;
}
@@ -141,20 +140,20 @@ public:
* sending a slot the same address too frequently.
*/
void
insert(beast::IP::Endpoint const& ep, std::uint32_t hops);
insert(beast::ip::Endpoint const& ep, std::uint32_t hops);
/**
* Returns `true` if we should not send endpoint to the slot.
*/
bool
filter(beast::IP::Endpoint const& ep, std::uint32_t hops);
filter(beast::ip::Endpoint const& ep, std::uint32_t hops);
private:
void
expire();
friend class SlotImp;
beast::aged_unordered_map<beast::IP::Endpoint, std::uint32_t> cache_;
beast::aged_unordered_map<beast::ip::Endpoint, std::uint32_t> cache_;
} recent;
void
@@ -168,11 +167,11 @@ private:
bool const fixed_;
bool reserved_;
State state_;
beast::IP::Endpoint remoteEndpoint_;
std::optional<beast::IP::Endpoint> localEndpoint_;
beast::ip::Endpoint remoteEndpoint_;
std::optional<beast::ip::Endpoint> localEndpoint_;
std::optional<PublicKey> publicKey_;
static constexpr std::int32_t kUnknownPort = -1;
static std::int32_t constexpr kUnknownPort = -1;
std::atomic<std::int32_t> listeningPort_;
public:
@@ -197,4 +196,4 @@ public:
clock_type::time_point whenAcceptEndpoints;
};
} // namespace xrpl::PeerFinder
} // namespace xrpl::peer_finder

View File

@@ -1,14 +1,13 @@
#pragma once
#include <xrpld/peerfinder/PeerfinderManager.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/peerfinder/Types.h>
#include <boost/system/error_code.hpp>
#include <string>
namespace xrpl::PeerFinder {
namespace xrpl::peer_finder {
/**
* A static or dynamic source of peer addresses.
@@ -47,4 +46,4 @@ public:
fetch(Results& results, beast::Journal journal) = 0;
};
} // namespace xrpl::PeerFinder
} // namespace xrpl::peer_finder

View File

@@ -1,12 +1,12 @@
#pragma once
#include <xrpld/peerfinder/detail/Source.h>
#include <xrpl/peerfinder/detail/Source.h>
#include <memory>
#include <string>
#include <vector>
namespace xrpl::PeerFinder {
namespace xrpl::peer_finder {
/**
* Provides addresses from a static set of strings.
@@ -22,4 +22,4 @@ public:
make(std::string const& name, Strings const& strings);
};
} // namespace xrpl::PeerFinder
} // namespace xrpl::peer_finder

View File

@@ -6,7 +6,7 @@
#include <functional>
#include <vector>
namespace xrpl::PeerFinder {
namespace xrpl::peer_finder {
/**
* Abstract persistence for PeerFinder data.
@@ -17,7 +17,7 @@ public:
virtual ~Store() = default;
// load the bootstrap cache
using load_callback = std::function<void(beast::IP::Endpoint, int)>;
using load_callback = std::function<void(beast::ip::Endpoint, int)>;
virtual std::size_t
load(load_callback const& cb) = 0;
@@ -26,11 +26,11 @@ public:
{
explicit Entry() = default;
beast::IP::Endpoint endpoint;
beast::ip::Endpoint endpoint;
int valence{};
};
virtual void
save(std::vector<Entry> const& v) = 0;
};
} // namespace xrpl::PeerFinder
} // namespace xrpl::peer_finder

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