Compare commits

..

42 Commits

Author SHA1 Message Date
Ayaz Salikhov
00a178fb92 chore: Bump version to 3.3.0 2026-08-06 17:34:39 +01:00
Bart
39c8c293b3 chore: Bump version to 3.3.0-rc7 2026-08-04 17:11:00 -04:00
Pratik Mankawde
54cfdda00b fix: Increase manifest protocol message size cap and fix manifests relay
Signed-off-by: Pratik Mankawde <3397372+pratikmankawde@users.noreply.github.com>
2026-08-04 17:08:43 -04:00
Ed Hennis
15d08770bf Merge branch 'release/3.2.x' into ximinez/merge-321-to-330
* release/3.2.x:
  chore: Bump version to 3.2.1
  chore: Bump version to 3.2.1-rc1
  fix: Cap untrusted manifests per message and drop oversized ones
  fix: Reject oversized validator manifest before decoding
  fix: Reduce untrusted manifest cache cap to 100
  fix: Bound untrusted manifest cache
2026-08-04 13:28:52 -04:00
Pratik Mankawde
8461ded0d8 fix: Cap untrusted manifests per message and drop oversized ones 2026-08-03 12:00:11 -04:00
Ed Hennis
d4c1359921 chore: Bump version to 3.2.1 2026-07-31 19:46:17 -04:00
Bart
a88ba66fce chore: Bump version to 3.2.1-rc1 2026-07-31 19:43:19 -04:00
Valentin Balaschenko
4bd1d1ca2f fix: Cap untrusted manifests per message and drop oversized ones
Bound the number of manifests carried in a single TMManifests message
(kMaxManifestsPerMessage). Trusted manifests are always included and
processed; untrusted gossip is capped per message on both send and
receive, and the sender is charged only when untrusted entries are
actually skipped. Oversized TMManifests messages are dropped without
penalty at the protocol layer so an unpatched peer is not disconnected.

Complements the cache bound from #276/#323.
2026-07-31 19:43:18 -04:00
Bart
0cce5a06d9 fix: Reject oversized validator manifest before decoding 2026-07-31 19:43:18 -04:00
Pratik Mankawde
32a9cc4038 fix: Reduce untrusted manifest cache cap to 100 2026-07-31 19:43:15 -04:00
Pratik Mankawde
587505ef18 fix: Bound untrusted manifest cache 2026-07-31 19:43:04 -04:00
Bart
4eece4003d chore: Bump version to 3.3.0-rc6 2026-07-30 16:34:46 +01:00
Ayaz Salikhov
3ad6ce236e feat: Package validator-keys inside rippled 2026-07-30 11:29:37 -04:00
Bart
ccb9db0bc7 chore: Bump version to 3.3.0-rc5 2026-07-29 14:25:13 -04:00
Mayukha Vadari
24b6dad287 fix: Switch SponsorshipSet to use a delta for sfFeeAmount 2026-07-29 14:24:55 -04:00
Bart
e290005db5 fix: Re-revert "fix: Set request size limits and differential pricing for get-object-by-hash calls" 2026-07-28 14:02:49 -04:00
Bart
6668b7e8d0 chore: Bump version to 3.3.0-rc4 2026-07-24 18:40:02 -04:00
Bart
a5cc339d7b fix: Revert "fix: Set request size limits and differential pricing for get-object-by-hash calls" 2026-07-24 18:39:35 -04:00
Bart
1653f0c80f chore: Bump version to 3.3.0-rc3 2026-07-23 16:39:50 -04:00
Pratik Mankawde
c50edf507c fix: Reduce untrusted manifest cache cap to 100 2026-07-23 16:27:45 -04:00
Valentin Balaschenko
9cd531659a fix: Revert "fix: Reject oversized SHAMap nodes in gotStaleData and fetch-pack path" 2026-07-23 14:53:15 -04:00
Bart
982bf36dd8 chore: Bump version to 3.3.0-rc2 2026-07-17 17:09:13 -04:00
Denis Angell
faca302adf fix: Check transaction type before RawTransactions 2026-07-17 17:08:57 -04:00
Shawn Xie
6b3eaf091b fix: Change ConfidentialMPTConvert to no delegate 2026-07-17 16:06:17 -04:00
Pratik Mankawde
68a765d929 fix: Bound untrusted manifest cache 2026-07-17 14:07:57 -04:00
yinyiqian1
033dca2f0e feat: Make DynamicMPT opt-in-immutable 2026-07-17 14:02:35 -04:00
Ayaz Salikhov
bf65e5fa7b chore: Upload codecov for whole XRPLF org 2026-07-17 11:20:28 -04:00
Valentin Balaschenko
90b2a68da8 fix: Reject oversized SHAMap nodes in gotStaleData and fetch-pack path 2026-07-17 08:07:42 -04:00
Ayaz Salikhov
06a9b1b617 chore: Update mpt-crypto to 1.0.2 2026-07-17 08:07:01 -04:00
Jingchen
7d3611df2a fix: Compute validation suppression key over canonical serialisation 2026-07-17 07:33:44 -04:00
Bart
7877ee42a0 fix: Reject oversized validator manifest before decoding 2026-07-16 16:33:03 -04:00
Bart
1dcaf4b54e fix: Bound and offload per-connection subscription cleanup 2026-07-16 16:33:03 -04:00
Bart
5ab95748d4 refactor: Clean up pong replies 2026-07-16 16:33:03 -04:00
Bart
4a9ee54c88 fix: Handle malformed ledger replay responses 2026-07-16 16:33:03 -04:00
Bart
981c256933 fix: Use weighted median for close-time offset aggregation 2026-07-16 16:33:03 -04:00
Bart
a5af6b4e4a fix: Charge kFeeHeavyBurdenRpc in doChannelVerify 2026-07-16 16:33:03 -04:00
Bart
e1dae5f775 refactor: Use tecPSEUDO_ACCOUNT instead of tecNO_PERMISSION where relevant 2026-07-16 16:32:54 -04:00
Timothy Banks
6c793edf72 fix: Reject oversized TMPing messages 2026-07-16 15:07:36 -04:00
Timothy Banks
d60955e2fc fix: Acquire lock on getClosedLedgerHash 2026-07-16 12:41:34 -04:00
Timothy Banks
846369cbe7 fix: Use hashmap for quicker lookup in assembleAdd 2026-07-16 12:16:09 -04:00
Mayukha Vadari
d569f7db9e fix: Prevent credentials from being created for pseudo-accounts 2026-07-16 11:42:27 -04:00
Mayukha Vadari
a12ab0496c fix: Add missing pseudo-account checks 2026-07-16 11:18:26 -04:00
647 changed files with 25488 additions and 29015 deletions

View File

@@ -75,8 +75,6 @@ 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
@@ -85,8 +83,6 @@ 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,9 +30,7 @@ ignoreRegExpList:
- ABCDEFGHIJKLMNOPQRSTUVWXYZ
- ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
overrides:
- filename:
- "**/*_test.cpp" # legacy boost.test files
- "src/tests/**/*.cpp" # gtest test files
- filename: "**/*_test.cpp" # all test files
ignoreRegExpList:
- /"[^"]*"/g # double-quoted strings
- /'[^']*'/g # single-quoted strings
@@ -132,6 +130,7 @@ words:
- godexsoft
- gpgcheck
- gpgkey
- Hinnant
- hotwallet
- hwaddress
- hwrap
@@ -165,6 +164,7 @@ words:
- llection
- LOCALGOOD
- logwstream
- Lombrozo
- lseq
- lsmf
- ltype
@@ -174,6 +174,7 @@ words:
- MPTAMM
- MPTDEX
- Merkle
- Metafuncton
- misprediction
- missingok
- mptbalance
@@ -201,6 +202,7 @@ words:
- nftokens
- nftpage
- nikb
- Nikolaos
- nixfmt
- nixos
- nixpkgs
@@ -217,7 +219,6 @@ words:
- Nyffenegger
- onlatest
- ostr
- oxalica
- pargs
- partitioner
- paychan
@@ -264,8 +265,6 @@ words:
- Rohrs
- roundings
- rustc
- rustfmt
- rustup
- sahyadri
- Satoshi
- scons
@@ -309,7 +308,6 @@ words:
- takerpays
- ters
- TMEndpointv2
- toolchain
- tparam
- trixie
- tx
@@ -342,7 +340,6 @@ words:
- unsquelch
- unsquelched
- unsquelching
- unsuffixed
- unvalidated
- unveto
- unvetoed

2
.envrc
View File

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

View File

@@ -11,9 +11,6 @@ endfunction()
function(create_symbolic_link target link)
endfunction()
function(xrpl_add_benchmark name)
endfunction()
macro(exclude_from_default target_)
endmacro()

View File

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

View File

@@ -1,10 +1,10 @@
<!--
This PR template helps you write a good pull request description.
This PR template helps you to write a good pull request description.
Please feel free to include additional useful information even beyond what is requested below.
If your branch is on a personal fork and has a name that allows it to
run CI build/test jobs (e.g. "ci/foo"), remember to rename it BEFORE
opening the PR. This avoids redundant test runs. Renaming
opening the PR. This avoids unnecessary redundant test runs. Renaming
the branch after opening the PR will close the PR.
https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-branches-in-your-repository/renaming-a-branch
-->
@@ -15,7 +15,7 @@ https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-
Please include a summary of the changes.
This may be a direct input to the release notes.
If too broad, please consider splitting into multiple PRs.
If there is a relevant task or issue, please link it here.
If a relevant task or issue, please link it here.
-->
### Context of Change
@@ -65,5 +65,5 @@ This section may not be needed if your change includes thoroughly commented unit
<!--
## Future Tasks
For future tasks related to this PR.
For future tasks related to PR.
-->

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 xrpl/consensus |
| 07 | xrpl/shamap |
## xrpld Modules (Application Implementation)
| 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 |
| 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 |
## Test Modules

View File

@@ -1,6 +1,9 @@
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

@@ -1,13 +1,8 @@
benchmarks.libxrpl > xrpl.basics
benchmarks.libxrpl > xrpl.config
benchmarks.libxrpl > xrpl.nodestore
libxrpl.basics > xrpl.basics
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
@@ -27,9 +22,6 @@ 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
@@ -65,9 +57,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
@@ -88,9 +80,12 @@ 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
@@ -105,6 +100,10 @@ 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
@@ -130,9 +129,12 @@ 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
@@ -141,13 +143,19 @@ 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
@@ -181,13 +189,11 @@ 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
@@ -197,10 +203,6 @@ 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
@@ -215,8 +217,6 @@ 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
@@ -243,20 +243,23 @@ 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
@@ -265,22 +268,21 @@ 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 > xrpld.app
xrpld.peerfinder > xrpl.config
xrpld.peerfinder > xrpld.core
xrpld.peerfinder > xrpl.peerfinder
xrpld.peerfinder > xrpl.protocol
xrpld.peerfinder > xrpl.rdb
xrpld.perflog > xrpl.basics
xrpld.perflog > xrpl.config

View File

@@ -46,6 +46,9 @@ 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

@@ -33,10 +33,6 @@ def get_cmake_args(build_type: str, extra_args: str) -> str:
# Every config must declare 'minimal'. Minimal configs form the reduced matrix
# built for pull requests by default; the full matrix adds the rest. Packaging
# configs declare it too, but packaging is gated in the workflow, not by it.
#
# Configs may also opt into 'benchmark' to smoke-run the benchmarks. Note that
# the flag applies to every entry a config expands into, so only set it on
# configs that expand to a single combination.
@dataclasses.dataclass
@@ -47,7 +43,6 @@ class LinuxConfig:
build_type: list[str]
arch: list[str]
minimal: bool
benchmark: bool = False # if true, smoke-run the benchmarks after testing
sanitizers: list[str] = dataclasses.field(default_factory=list)
suffix: str = ""
extra_cmake_args: str = ""
@@ -86,7 +81,6 @@ class PlatformConfig:
build_type: list[str]
minimal: bool
build_only: bool = False # if true, skip tests (e.g. macos/Windows Debug)
benchmark: bool = False # if true, smoke-run the benchmarks after testing
extra_cmake_args: str = ""
def __post_init__(self) -> None:
@@ -131,7 +125,6 @@ class MatrixEntry:
cmake_args: str
cmake_target: str
build_only: bool
benchmark: bool
build_type: str
architecture: Architecture
sanitizers: str
@@ -143,7 +136,8 @@ class MatrixEntry:
class PackagingEntry:
"""One entry in the generated packaging strategy matrix."""
artifact_name: str
xrpld_artifact_name: str
validator_keys_artifact_name: str
image: str
distro: str # e.g. "debian" or "rhel"; drives package-format-specific steps
@@ -200,7 +194,6 @@ def expand_linux_matrix(linux: LinuxFile, minimal: bool) -> list[MatrixEntry]:
cmake_args=get_cmake_args(build_type, cfg.extra_cmake_args),
cmake_target="all",
build_only=False,
benchmark=cfg.benchmark,
build_type=build_type,
architecture=arch_info,
sanitizers=sanitizer,
@@ -218,14 +211,19 @@ def expand_linux_packaging(linux: LinuxFile) -> list[PackagingEntry]:
the nix-based build images, because deb/rpm tooling (debhelper, rpm-build)
is taken from the distro's archive rather than from nixpkgs. Each config
entry carries its own 'image'.
The artifact names must match what the build job uploads: one artifact per
binary, each named after the build config.
"""
entries = []
for distro, configs in linux.package_configs.items():
for cfg in configs:
for compiler, build_type in itertools.product(cfg.compiler, cfg.build_type):
config_name = f"{distro}-{compiler}-{build_type.lower()}-amd64"
entries.append(
PackagingEntry(
artifact_name=f"xrpld-{distro}-{compiler}-{build_type.lower()}-amd64",
xrpld_artifact_name=f"xrpld-{config_name}",
validator_keys_artifact_name=f"validator-keys-{config_name}",
image=cfg.image,
distro=distro,
)
@@ -253,7 +251,6 @@ def expand_platform_matrix(pf: PlatformFile, minimal: bool) -> list[MatrixEntry]
cmake_args=get_cmake_args(build_type, cfg.extra_cmake_args),
cmake_target="install" if is_windows else "all",
build_only=cfg.build_only,
benchmark=cfg.benchmark,
build_type=build_type,
architecture=Architecture(platform=pf.platform, runner=pf.runner),
sanitizers="",

View File

@@ -1,23 +1,13 @@
{
"image_tag": "sha-fecfc0c",
"image_tag": "sha-e29b523",
"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,
"benchmark": true
"minimal": true
},
{
"compiler": ["gcc"],
"build_type": ["Release"],
@@ -39,6 +29,14 @@
"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"],
@@ -70,7 +68,8 @@
"compiler": ["gcc"],
"build_type": ["Release"],
"arch": ["amd64"],
"minimal": false
"minimal": false,
"extra_cmake_args": "-Dvalidator_keys=ON"
}
],
@@ -79,7 +78,8 @@
"compiler": ["gcc"],
"build_type": ["Release"],
"arch": ["amd64"],
"minimal": false
"minimal": false,
"extra_cmake_args": "-Dvalidator_keys=ON"
}
]
},

View File

@@ -1,4 +1,4 @@
name: Build `nix` Docker images
name: Build Nix Docker images
on:
push:
@@ -8,24 +8,20 @@ on:
- ".github/workflows/build-nix-images.yml"
- "flake.nix"
- "flake.lock"
- "rust-toolchain.toml"
- "nix/**"
- "!nix/docker/README.md"
- "!nix/devshell.nix"
- "bin/check-tools.sh"
- "bin/default-loader-path.sh"
- "bin/install-sanitizer-libs.sh"
pull_request:
paths:
- ".github/workflows/build-nix-images.yml"
- "flake.nix"
- "flake.lock"
- "rust-toolchain.toml"
- "nix/**"
- "!nix/docker/README.md"
- "!nix/devshell.nix"
- "bin/check-tools.sh"
- "bin/default-loader-path.sh"
- "bin/install-sanitizer-libs.sh"
workflow_dispatch:
@@ -40,7 +36,7 @@ defaults:
jobs:
build-merge:
name: Build and push `nix-${{ matrix.distro.name }}` image
name: Build and push nix-${{ matrix.distro.name }}
permissions:
contents: read
packages: write
@@ -58,7 +54,7 @@ jobs:
base_image: debian:bookworm
- name: rhel
base_image: registry.access.redhat.com/ubi9/ubi:latest
uses: XRPLF/actions/.github/workflows/build-multiarch-image.yml@9e7e4e80af9e684c116b38369add8eea64451f32
uses: XRPLF/actions/.github/workflows/build-multiarch-image.yml@ee03d31bcc4501d7599dc1b1ecd7a34af582ad1c
with:
image_name: xrpld/nix-${{ matrix.distro.name }}
dockerfile: nix/docker/Dockerfile

View File

@@ -1,4 +1,4 @@
name: Build `packaging` Docker images
name: Build packaging Docker images
on:
push:
@@ -26,7 +26,7 @@ defaults:
jobs:
build-merge:
name: Build and push `packaging-${{ matrix.distro.name }}` image
name: Build and push packaging-${{ matrix.distro.name }}
permissions:
contents: read
packages: write
@@ -38,7 +38,7 @@ jobs:
base_image: debian:bookworm
- name: rhel
base_image: registry.access.redhat.com/ubi9/ubi:latest
uses: XRPLF/actions/.github/workflows/build-multiarch-image.yml@9e7e4e80af9e684c116b38369add8eea64451f32
uses: XRPLF/actions/.github/workflows/build-multiarch-image.yml@ee03d31bcc4501d7599dc1b1ecd7a34af582ad1c
with:
image_name: xrpld/packaging-${{ matrix.distro.name }}
dockerfile: package/Dockerfile

View File

@@ -1,38 +0,0 @@
name: Build `pre-commit` Docker image
on:
push:
branches:
- develop
paths:
- ".github/workflows/build-pre-commit-image.yml"
- "bin/pre-commit/Dockerfile"
- "rust-toolchain.toml"
pull_request:
paths:
- ".github/workflows/build-pre-commit-image.yml"
- "bin/pre-commit/Dockerfile"
- "rust-toolchain.toml"
workflow_dispatch:
concurrency:
# Read `on-trigger.yml` for the rationale behind this concurrency group name.
group: ${{ github.workflow }}-${{ github.event_name == 'push' && github.ref == 'refs/heads/develop' && github.sha || github.ref }}
cancel-in-progress: true
defaults:
run:
shell: bash
jobs:
build-merge:
name: Build and push `pre-commit` image
permissions:
contents: read
packages: write
uses: XRPLF/actions/.github/workflows/build-multiarch-image.yml@9e7e4e80af9e684c116b38369add8eea64451f32
with:
image_name: xrpld/pre-commit
dockerfile: bin/pre-commit/Dockerfile
base_image: ubuntu:26.04
push: ${{ github.event_name == 'push' }}

View File

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

View File

@@ -20,4 +20,4 @@ on:
jobs:
check_title:
if: ${{ github.event.pull_request.draft != true }}
uses: XRPLF/actions/.github/workflows/check-pr-title.yml@d7c65e49225a38f6d8010eacf017bb5a98d7476c
uses: XRPLF/actions/.github/workflows/check-pr-title.yml@cba1f0891650baf1a9c88624dc2d72573be2eb81

View File

@@ -1,114 +0,0 @@
# 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@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- 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,7 +90,6 @@ jobs:
.clang-tidy
.codecov.yml
bin/check-tools.sh
bin/default-loader-path.sh
cfg/**
cmake/**
conan/**

View File

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

View File

@@ -14,7 +14,7 @@ on:
jobs:
# Call the workflow in the XRPLF/actions repo that runs the pre-commit hooks.
run-hooks:
uses: XRPLF/actions/.github/workflows/pre-commit.yml@3ba08d6ddf114092891d48491fc2e26c3ba15552
uses: XRPLF/actions/.github/workflows/pre-commit.yml@1bde119a1ab71305ba5d3716e7a82cea1c7bdede
with:
runs_on: ubuntu-latest
container: '{ "image": "ghcr.io/xrplf/xrpld/pre-commit:sha-f56b79f" }'
container: '{ "image": "ghcr.io/xrplf/ci/tools-rippled-pre-commit:sha-41ec7c1" }'

View File

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

View File

@@ -3,12 +3,6 @@ name: Build and test configuration
on:
workflow_call:
inputs:
benchmark:
description: "Whether to smoke-run the benchmarks after testing."
required: false
type: boolean
default: false
build_only:
description: 'Whether to only build or to build and test the code ("true", "false").'
required: true
@@ -106,9 +100,10 @@ jobs:
# header files are copied into separate directories by CMake, which will
# otherwise result in cache misses.
CCACHE_SLOPPINESS: include_file_ctime,include_file_mtime
# Determine if coverage and voidstar should be enabled.
# Determine if coverage, voidstar and validator-keys should be enabled.
COVERAGE_ENABLED: ${{ contains(inputs.cmake_args, '-Dcoverage=ON') }}
VOIDSTAR_ENABLED: ${{ contains(inputs.cmake_args, '-Dvoidstar=ON') }}
VALIDATOR_KEYS_ENABLED: ${{ contains(inputs.cmake_args, '-Dvalidator_keys=ON') }}
SANITIZERS_ENABLED: ${{ inputs.sanitizers != '' }}
steps:
- name: Cleanup workspace (macOS and Windows)
@@ -116,10 +111,10 @@ jobs:
uses: XRPLF/actions/cleanup-workspace@c7d9ce5ebb03c752a354889ecd870cadfc2b1cd4
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@c00c22ada3bd6bcda48fcb0d62fbbab49fec8a0f
uses: XRPLF/actions/prepare-runner@64ec3cf3b152b4444638f470bbd6df7a7a30c81c
with:
enable_ccache: ${{ inputs.ccache_enabled }}
@@ -229,13 +224,11 @@ jobs:
BUILD_TYPE: ${{ inputs.build_type }}
CMAKE_TARGET: ${{ inputs.cmake_target }}
run: |
set -o pipefail
cmake \
--build . \
--config "${BUILD_TYPE}" \
--parallel "${BUILD_NPROC}" \
--target "${CMAKE_TARGET}" \
2>&1 | tee "${GITHUB_WORKSPACE}/build.log"
--target "${CMAKE_TARGET}"
- name: Show ccache statistics
if: ${{ inputs.ccache_enabled }}
@@ -255,6 +248,22 @@ jobs:
retention-days: 3
if-no-files-found: error
- name: Run the validator-keys tests
if: ${{ env.VALIDATOR_KEYS_ENABLED == 'true' }}
working-directory: ${{ env.BUILD_DIR }}
run: ./validator-keys --unittest
- name: Upload the validator-keys binary
if: ${{ github.event.repository.visibility == 'public' && env.VALIDATOR_KEYS_ENABLED == 'true' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: validator-keys-${{ inputs.config_name }}
path: |
${{ env.BUILD_DIR }}/validator-keys
${{ env.BUILD_DIR }}/validator-keys-LICENSE
retention-days: 3
if-no-files-found: error
- name: Upload the test binary (Linux)
if: ${{ github.event.repository.visibility == 'public' && runner.os == 'Linux' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
@@ -272,7 +281,7 @@ jobs:
./xrpld --definitions | python3 -m json.tool >server_definitions.json
- name: Upload server definitions
if: ${{ github.event.repository.visibility == 'public' && inputs.config_name == 'ubuntu-gcc-debug-amd64-coverage' }}
if: ${{ github.event.repository.visibility == 'public' && inputs.config_name == 'debian-gcc-release-amd64' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: server-definitions
@@ -330,49 +339,27 @@ jobs:
PRELOAD=""
fi
LD_PRELOAD="$PRELOAD" ./xrpld --unittest --unittest-jobs "${BUILD_NPROC}" 2>&1 | tee "${GITHUB_WORKSPACE}/unittest.log"
LD_PRELOAD="$PRELOAD" ./xrpld --unittest --unittest-jobs "${BUILD_NPROC}" 2>&1 | tee unittest.log
# Smoke-run every benchmark module with a single repetition to confirm the
# benchmarks still build and execute. This is a correctness check, not a
# performance measurement, so there is nothing to gain from repeating it
# across configurations: it is opted into by a single config in the
# strategy matrix (see the 'benchmark' flag in the JSON files), which
# keeps it off instrumented builds (sanitizers/coverage/voidstar), where
# it would be slow and meaningless, off Debug builds, where it is much
# slower, and off Windows, where the `install` target does not build them.
- name: Run the benchmarks
if: ${{ inputs.benchmark }}
working-directory: ${{ env.BUILD_DIR }}
- name: Show test failure summary
if: ${{ failure() && !inputs.build_only }}
env:
WORKING_DIR: ${{ runner.os == 'Windows' && format('{0}\{1}', env.BUILD_DIR, inputs.build_type) || env.BUILD_DIR }}
run: |
rc=0
while IFS= read -r bench; do
echo "::group::${bench}"
"./${bench}" --benchmark_repetitions=1 || rc=1
echo "::endgroup::"
done < <(find src/benchmarks -type f -perm -u+x -name 'xrpl.bench.*')
exit "${rc}"
if [ ! -d "${WORKING_DIR}" ]; then
echo "Working directory '${WORKING_DIR}' does not exist."
exit 0
fi
- name: Show build/test failure summary
if: ${{ failure() }}
run: |
cd "${GITHUB_WORKSPACE}"
cd "${WORKING_DIR}"
if [ -f unittest.log ]; then
if ! grep -E "failed" unittest.log | grep -vE "^I[0-9]|^[0-9]+> (ERR:|FTL:)"; then
echo "unittest.log present but no failure lines found."
fi
elif [ -f build.log ]; then
# GCC/Clang emit "error:" (covers "fatal error:"); MSVC emits
# "error C####:", "error LNK####:", and "fatal error LNK####:".
# -A6 prints the lines that follow each match (source line, caret,
# notes, and the "N errors generated" tally) to capture the whole
# diagnostic block.
if ! grep -E -A6 "error:|error C[0-9]{4}|error LNK[0-9]{4}|fatal error" build.log; then
echo "build.log present but no compile errors found."
fi
else
echo "unittest.log/build.log not found; something went wrong."
exit 1
if [ ! -f unittest.log ]; then
echo "unittest.log not found; embedded tests may not have run."
exit 0
fi
if ! grep -E "failed" unittest.log; then
echo "Log present but no failure lines found in unittest.log."
fi
- name: Debug failure (Linux)
if: ${{ failure() && runner.os == 'Linux' && !inputs.build_only }}
@@ -396,7 +383,7 @@ jobs:
--target coverage
- name: Upload coverage report
if: ${{ github.repository == 'XRPLF/rippled' && !inputs.build_only && env.COVERAGE_ENABLED == 'true' }}
if: ${{ github.repository_owner == 'XRPLF' && !inputs.build_only && env.COVERAGE_ENABLED == 'true' }}
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
with:
disable_search: true

View File

@@ -40,7 +40,6 @@ jobs:
fail-fast: ${{ github.event_name == 'merge_group' }}
matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}
with:
benchmark: ${{ matrix.benchmark }}
build_only: ${{ matrix.build_only }}
build_type: ${{ matrix.build_type }}
ccache_enabled: ${{ inputs.ccache_enabled }}

View File

@@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- 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@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- 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-fecfc0c"
container: "ghcr.io/xrplf/xrpld/nix-debian:sha-e29b523"
permissions:
contents: read
issues: write
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@c00c22ada3bd6bcda48fcb0d62fbbab49fec8a0f
uses: XRPLF/actions/prepare-runner@64ec3cf3b152b4444638f470bbd6df7a7a30c81c
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 -format -allow-no-checks ${TARGETS} 2>&1 | tee "${OUTPUT_FILE}"
run-clang-tidy -j ${{ steps.nproc.outputs.nproc }} -p "${BUILD_DIR}" -quiet -fix -allow-no-checks ${TARGETS} 2>&1 | tee "${OUTPUT_FILE}"
- name: Print filtered clang-tidy errors
if: ${{ steps.run_clang_tidy.outcome != 'success' }}

View File

@@ -1,7 +1,7 @@
# Build Linux packages (DEB and RPM) from pre-built binary artifacts.
# Discovers which configurations to package from linux.json (configs in
# "package_configs") and fans out one job per distro. Only linux/amd64 is
# supported; the runner is hardcoded in the job below.
# Build Linux packages (DEB and RPM) from pre-built binary artifacts (xrpld and
# validator-keys). Discovers which configurations to package from linux.json
# (configs in "package_configs") and fans out one job per distro. Only
# linux/amd64 is supported; the runner is hardcoded in the job below.
name: Package
on:
@@ -27,10 +27,10 @@ jobs:
matrix: ${{ steps.generate.outputs.matrix }}
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.13"
@@ -45,7 +45,7 @@ jobs:
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}
name: "${{ matrix.artifact_name }}"
name: "${{ matrix.xrpld_artifact_name }}"
permissions:
contents: read
runs-on: ["self-hosted", "Linux", "X64", "heavy"]
@@ -54,16 +54,22 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Download pre-built binary
- name: Download pre-built xrpld binary
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: ${{ matrix.artifact_name }}
name: ${{ matrix.xrpld_artifact_name }}
path: ${{ env.BUILD_DIR }}
- name: Make binary executable
run: chmod +x "${BUILD_DIR}/xrpld"
- name: Download pre-built validator-keys binary
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: ${{ matrix.validator_keys_artifact_name }}
path: ${{ env.BUILD_DIR }}
- name: Make binaries executable
run: chmod +x "${BUILD_DIR}/xrpld" "${BUILD_DIR}/validator-keys"
- name: Build package
env:
@@ -73,7 +79,7 @@ jobs:
- name: Upload package artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ${{ matrix.artifact_name }}-pkg
name: ${{ matrix.xrpld_artifact_name }}-pkg
path: |
${{ env.BUILD_DIR }}/debbuild/*.deb
${{ env.BUILD_DIR }}/debbuild/*.ddeb

View File

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

View File

@@ -40,14 +40,14 @@ defaults:
jobs:
upload:
runs-on: ubuntu-latest
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-fecfc0c
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-e29b523
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@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- 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@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@c00c22ada3bd6bcda48fcb0d62fbbab49fec8a0f
uses: XRPLF/actions/prepare-runner@64ec3cf3b152b4444638f470bbd6df7a7a30c81c
with:
enable_ccache: false

3
.gitignore vendored
View File

@@ -81,9 +81,6 @@ DerivedData
# Python
__pycache__
# Rust build artifacts.
target/
# Direnv's directory
/.direnv

View File

@@ -55,7 +55,7 @@ repos:
types_or: [c++, c]
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: f4d7745e17a28aad7eed2f4874ca8d1568c11c4c # frozen: v22.1.8
rev: dd18dad857d6133e90bbe478f4f2f22ec0030269 # frozen: v22.1.5
hooks:
- id: clang-format
args: [--style=file]
@@ -68,7 +68,7 @@ repos:
- id: gersemi
- repo: https://github.com/rbubley/mirrors-prettier
rev: 9337a74165b178ae2c766f60bee7252a0f06f3e8 # frozen: v3.9.5
rev: 39e2973981e6d2f9b6c543b0086a2d2393abdc89 # frozen: v3.9.4
hooks:
- id: prettier
args: [--end-of-line=auto]

View File

@@ -28,8 +28,6 @@ This section contains changes targeting a future version.
### Additions
- `server_info` (admin): The `node_size` field has been removed along with the deprecated `[node_size]` config setting it reported. Admin responses now include `memory_limit`, the cache memory budget in gigabytes (0 when enforcement is disabled).
- `account_tx`: Added an optional `delegate` request object to filter delegated transactions. The object requires `delegate_filter`, which must be either `actor` for transactions owned by the requested account but signed by another account, or `authorizer` for transactions signed by the requested account on behalf of another account. The optional `counter_party` account narrows the results to a specific signer/delegate for `actor` or a specific owner/delegator for `authorizer`. Malformed `delegate`, `delegate_filter`, and `counter_party` values return standard invalid field errors, and invalid account IDs return `actMalformed`.
When paginating delegate-filtered queries, a marker from a delegate-filtered query includes a `delegate` flag and is only valid for follow-up requests that also supply `delegate` (mixing marker conventions returns `invalidParams`). Because filtering is applied after the ledger scan, a page may contain fewer results than `limit` (possibly zero) while still returning a marker, so callers must continue until no marker is present.

View File

@@ -42,8 +42,6 @@ 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,23 +13,6 @@ 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)
@@ -104,7 +87,6 @@ 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)
@@ -120,7 +102,6 @@ target_link_libraries(
xrpl_libs
INTERFACE
ed25519::ed25519
FastFloat::fast_float
lz4::lz4
mpt-crypto::mpt-crypto
OpenSSL::Crypto
@@ -150,10 +131,6 @@ else()
endif()
target_link_libraries(xrpl_libs INTERFACE ${nudb})
if(benchmark)
find_package(benchmark REQUIRED)
endif()
if(coverage)
include(XrplCov)
endif()
@@ -161,14 +138,12 @@ endif()
include(XrplCore)
include(XrplProtocolAutogen)
include(XrplInstall)
include(XrplPackaging)
include(XrplValidatorKeys)
# Must come after XrplValidatorKeys: the 'package' target depends on the
# validator-keys target existing.
include(XrplPackaging)
if(tests)
include(CTest)
add_subdirectory(src/tests/libxrpl)
endif()
if(benchmark)
add_subdirectory(src/benchmarks/libxrpl)
endif()

View File

@@ -1,4 +0,0 @@
# By default, anyone can review changes.
# The CI tooling team should review changes to the CI configuration.
/.github/ @XRPLF/ci-tooling

View File

@@ -83,7 +83,6 @@ If you create new source files, they must be organized as follows:
`src/libxrpl`.
- All other non-test files must go under `src/xrpld`.
- All test source files must go under `src/test`.
- All benchmark source files must go under `src/benchmarks`.
The source must be formatted according to the style guide below. The easiest
way to satisfy this is to install the [`pre-commit`](#pre-commit-hooks) hooks,
@@ -348,14 +347,12 @@ 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 -format` to the above command:
If you wish to automatically fix whatever clang-tidy finds _and_ is capable of fixing, add `-fix` to the above command:
```
run-clang-tidy -p build -quiet -fix -format -allow-no-checks src tests
run-clang-tidy -p build -quiet -fix -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,10 +30,8 @@ missing=()
checked=0
# check <name> [probe-command...]
# 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.
# Runs the probe (default: "<name> --version") quietly. Records <name> as
# missing if the command is not found or exits non-zero.
check() {
local name="$1"
shift
@@ -42,11 +40,10 @@ check() {
probe=("${name}" --version)
fi
echo "Checking ${name}..."
checked=$((checked + 1))
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}"
if "${probe[@]}" | head -n 1; then
printf ' [ ok ] %s\n' "${name}"
else
printf ' [MISS] %s\n' "${name}"
missing+=("${name}")
@@ -88,14 +85,12 @@ if [ "${os}" = "linux" ] || [ "${os}" = "macos" ]; then
check file
check less
check make
# 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 netstat which netstat
check ninja
check perl perl -e 'print "$^V\n"'
check perl
check pkg-config
check vim
check zip bash -c 'zip --version 2>&1 | grep -m1 -oE "Zip [0-9.]+"'
check zip
# 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

@@ -1,55 +0,0 @@
ARG BASE_IMAGE=ubuntu:26.04
FROM ${BASE_IMAGE}
SHELL ["/bin/bash", "-e", "-o", "pipefail", "-c"]
ENTRYPOINT ["/bin/bash"]
ARG DEBIAN_FRONTEND=noninteractive
RUN <<EOF
pkgs=()
pkgs+=(curl) # Required to install nix.
pkgs+=(doxygen) # Needed for Clio's check-doxygen-docs.sh.
pkgs+=(git) # Required for prepare-runner.
pkgs+=(libatomic1) # Required to run pre-commit provided `node`.
pkgs+=(python3) # Python 3 interpreter.
pkgs+=(python3-pip) # Package manager for Python applications.
pkgs+=(xz-utils) # Required to install nix
apt-get update
apt-get install -y --no-install-recommends "${pkgs[@]}"
apt-get clean
rm -rf /var/lib/apt/lists/*
EOF
ARG PRE_COMMIT_VERSION=4.6.0
RUN pip install --no-cache --break-system-packages \
pre-commit==${PRE_COMMIT_VERSION}
RUN sh <(curl --proto '=https' --tlsv1.2 -L https://nixos.org/nix/install) --daemon --yes
# Add nix to PATH and set NIX environment variables,
# so nix is available in all shells including non-interactive shells (e.g., GitHub Actions).
ENV PATH="/nix/var/nix/profiles/default/bin:${PATH}"
ENV NIX_PROFILES="/nix/var/nix/profiles/default"
ENV NIX_SSL_CERT_FILE="/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt"
# Verify nix installation
RUN nix --version
ENV RUSTUP_HOME="/opt/rust/rustup"
ENV CARGO_HOME="/opt/rust/cargo"
ENV PATH="/opt/rust/cargo/bin:${PATH}"
WORKDIR /tmp
COPY rust-toolchain.toml /tmp/rust-toolchain.toml
RUN <<EOF
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \
| sh -s -- -y --no-modify-path --profile minimal --default-toolchain none
rustup toolchain install
rustup show
cargo fmt --version
EOF
WORKDIR /

View File

@@ -144,11 +144,7 @@ def main():
+ files
)
canonicalize_fix_paths(Path(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]
)
applied = subprocess.run([clang_apply_replacements, fixes_dir])
return result.returncode or applied.returncode

View File

@@ -488,6 +488,17 @@
# Must be a number between 100 and 1000, defaults to 250
#
#
# [max_subscriptions_per_connection]
#
# Maximum number of account, real-time account, and account-history
# subscriptions a single client connection may hold at once. Bounds the
# per-connection state torn down when the connection disconnects. Book
# subscriptions are tracked separately and are not counted here.
#
# Defaults to 100000 if not set; large enough for legitimate power users
# such as block explorers.
#
#
# [overlay]
#
# Controls settings related to the peer to peer overlay.
@@ -538,6 +549,45 @@
# only be used for local testing and debugging. Do not disable
# on mainnet.
#
# max_untrusted_count = <number>
#
# The number of manifests the server keeps for validators it does not
# list, and the number it sends and processes in a single peer protocol
# message. Once the server holds this many, a manifest for a new
# unlisted validator is rejected, so peer gossip cannot grow the cache
# without end.
#
# This option can take any value between 50 and 1000, inclusive. If
# the option is not present the server uses its built-in value.
#
# The current default (which is subject to change) is 300.
#
# max_trusted_count = <number>
#
# The number of manifests for listed validators to allow for when
# sizing peer protocol messages. Manifests for listed validators are
# never dropped, whether sending or receiving, because doing so would
# delay a validator key change reaching this server. Set this above the
# number of validators the server lists.
#
# Together the two counts above set the largest manifest message the
# server accepts: bigger messages are discarded without reading them,
# and without penalising the sender. Raising either means the server
# accepts and sends bigger messages than a peer using the defaults, and
# those peers will discard what this server sends. Lowering either below
# what peers send makes this server discard their manifest messages,
# which it does without recording anything.
#
# This option can take any value between 50 and 1000, inclusive. If
# the option is not present the server uses its built-in value.
#
# The current default (which is subject to change) is 300.
#
# NOTE: These two options (max_untrusted_count and max_trusted_count)
# are transitional. They exist to bound manifest-message size and cache
# growth during the network upgrade. They may be removed in a future
# release once the fleet has upgraded, and should not be relied upon as
# stable configuration.
#
# [transaction_queue] EXPERIMENTAL
#
@@ -1306,40 +1356,23 @@
#
# [node_size]
#
# DEPRECATED. Each size is now an alias for a [memory_limit] value:
# tiny = 4, small = 8, medium = 32, large = 64, huge = 128. Set
# [memory_limit] instead; setting this logs a warning at startup.
# Tunes the servers based on the expected load and available memory. Legal
# sizes are "tiny", "small", "medium", "large", and "huge". We recommend
# you start at the default and raise the setting if you have extra memory.
#
# [memory_limit]
# The code attempts to automatically determine the appropriate size for
# this parameter based on the amount of RAM and the number of execution
# cores available to the server. The current decision matrix is:
#
# The memory budget, in gigabytes, that the server sizes its caches
# within. Cache sizes scale with the budget; the SHAMap tree node cache
# is capped to fit within half of it, enforced as it grows. Defaults to
# detected physical RAM (capped by the container limit when one is set);
# 0 selects minimal sizes with no enforcement. Values above 1024 are
# rejected, and a value above detected RAM logs a warning.
# Set this when xrpld shares the machine with other services or runs in
# a container with a memory limit below the host's RAM. Thread counts
# are unrelated: they come from the core count and the [workers] /
# [io_workers] overrides.
#
# Example:
# memory_limit = 16
#
# [tree_cache_age]
#
# Seconds a SHAMap tree node stays cached after its last use. The default
# is 300. Accepted values are 10 to 3600.
#
# [ledger_cache_age]
#
# Seconds a full ledger stays in the ledger cache after its last use. The
# default is 180. Accepted values are 10 to 3600.
#
# [ledger_fetch_size]
#
# How many historical ledgers to acquire per fetch pass while backfilling.
# The default is 4. Accepted values are 1 to 16.
# | | Cores |
# |---------|------------------------|
# | RAM | 1 | 2 or 3 | ≥ 4 |
# |---------|------|--------|--------|
# | < ~8GB | tiny | tiny | tiny |
# | < ~12GB | tiny | small | small |
# | < ~16GB | tiny | small | medium |
# | < ~24GB | tiny | small | large |
# | < ~32GB | tiny | small | huge |
#
# [signing_support]
#

View File

@@ -29,27 +29,6 @@ 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,37 +1,26 @@
#[===================================================================[
Patch executables to run in non-Nix environments.
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.
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` resets
the interpreter to the system default loader and drops the rpath, once the
binary has been linked.
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.
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.
#]===================================================================]
include_guard(GLOBAL)
include(CompilationEnv)
# Resolves the system default ELF loader path for the current architecture.
set(_loader_path_script "${CMAKE_SOURCE_DIR}/bin/default-loader-path.sh")
# Provided by the Nix-based CI image; prints the system default ELF loader path.
set(_loader_path_script "/tmp/loader-path.sh")
if(
is_linux
AND NOT SANITIZERS_ENABLED
AND is_nix_compiler
AND NOT DEFINED ENV{XRPLD_NO_PATCH_NIX_BINARY}
)
if(is_linux AND NOT SANITIZERS_ENABLED AND EXISTS "${_loader_path_script}")
execute_process(
COMMAND "${_loader_path_script}"
OUTPUT_VARIABLE DEFAULT_LOADER_PATH
@@ -52,13 +41,38 @@ function(patch_nix_binary target)
if(NOT PATCH_NIX_BINARIES)
return()
endif()
add_custom_command(
TARGET ${target}
POST_BUILD
COMMAND
"${PATCHELF_COMMAND}" --set-interpreter "${DEFAULT_LOADER_PATH}"
--remove-rpath "$<TARGET_FILE:${target}>"
COMMENT "Patching ${target}: set default loader, remove rpath"
VERBATIM
set(patch_command
"${PATCHELF_COMMAND}"
--set-interpreter
"${DEFAULT_LOADER_PATH}"
--remove-rpath
"$<TARGET_FILE:${target}>"
)
set(comment "Patching ${target}: set default loader, remove rpath")
# POST_BUILD is the cheap way to do this: it runs only when the binary is
# relinked. It is also only available in the directory that defined the
# target, so for a target from elsewhere (e.g. a FetchContent subproject)
# fall back to a custom target that runs after the binary is linked. That
# one runs on every build, which is harmless because patchelf is idempotent.
get_target_property(target_source_dir ${target} SOURCE_DIR)
if("${target_source_dir}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}")
add_custom_command(
TARGET ${target}
POST_BUILD
COMMAND ${patch_command}
COMMENT "${comment}"
VERBATIM
)
else()
add_custom_target(
${target}-patch-nix
ALL
COMMAND ${patch_command}
COMMENT "${comment}"
VERBATIM
)
add_dependencies(${target}-patch-nix ${target})
endif()
endfunction()

View File

@@ -1,38 +0,0 @@
include_guard()
include(isolate_headers)
# Define a benchmark executable for the module `name`.
#
# This follows the same general pattern as other build helpers in this repo
# (e.g. `add_module`): create a target and isolate headers, but here the target
# is a benchmark executable and no `add_test(...)` is registered.
#
# `isolate_headers` exposes only `${CMAKE_CURRENT_SOURCE_DIR}/${name}` on the
# include path, rooted at `src`, so a benchmark's own headers are reached as
# `<benchmarks/.../${name}/...>` and nothing else in the tree leaks in.
function(xrpl_add_benchmark name)
set(target ${PROJECT_NAME}.bench.${name})
file(
GLOB_RECURSE sources
CONFIGURE_DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/${name}/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/${name}.cpp"
)
add_executable(${target} ${ARGN} ${sources})
# Benchmark sources register cases through Google Benchmark's static
# registrars (anonymous-namespace lambdas). Merging several such files into
# one unity translation unit collides those internal-linkage entities, so
# keep benchmarks out of the unity build - mirroring xrpl.libpb in
# XrplCore.cmake. Each file compiles fine on its own.
set_target_properties(${target} PROPERTIES UNITY_BUILD OFF)
isolate_headers(
${target}
"${CMAKE_SOURCE_DIR}/src"
"${CMAKE_CURRENT_SOURCE_DIR}/${name}"
PRIVATE
)
endfunction()

View File

@@ -171,8 +171,9 @@ 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(
is_nix_compiler
_cxx_real MATCHES "^/nix/store/"
AND is_linux
AND is_clang
AND CMAKE_CXX_FLAGS MATCHES "stdlib=libstdc"

View File

@@ -133,12 +133,6 @@ 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(
@@ -207,16 +201,6 @@ 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)
@@ -236,7 +220,6 @@ target_link_modules(
beast
conditions
config
consensus
core
crypto
git
@@ -244,7 +227,6 @@ target_link_modules(
ledger
net
nodestore
peerfinder
protocol
protocol_autogen
rdb

View File

@@ -25,6 +25,19 @@ if(NOT (RPMBUILD_EXECUTABLE OR DPKG_BUILDPACKAGE_EXECUTABLE))
return()
endif()
if(NOT TARGET xrpld)
message(STATUS "xrpld=ON is required; 'package' target not available")
return()
endif()
if(NOT TARGET validator-keys)
message(
STATUS
"validator_keys=ON is required; 'package' target not available"
)
return()
endif()
set(package_env
SRC_DIR=${CMAKE_SOURCE_DIR}
BUILD_DIR=${CMAKE_BINARY_DIR}
@@ -37,7 +50,7 @@ add_custom_target(
${CMAKE_COMMAND} -E env ${package_env}
${CMAKE_SOURCE_DIR}/package/build_pkg.sh
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
DEPENDS xrpld
DEPENDS xrpld validator-keys
COMMENT "Building Linux package (deb/rpm inferred from host tooling)"
VERBATIM
)

View File

@@ -36,19 +36,6 @@ 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

@@ -30,8 +30,6 @@ if(tests)
endif()
endif()
option(benchmark "Build benchmarks" ON)
# Enabled by default so every header is compiled on its own as the main file of
# its own compile_commands.json entry - this is what lets clang-tidy (and clangd
# and IDEs) analyse a header's own includes directly. The per-header objects are

View File

@@ -5,22 +5,39 @@ option(
)
if(validator_keys)
git_branch(current_branch)
# default to tracking VK master branch unless we are on release
if(NOT (current_branch STREQUAL "release"))
set(current_branch "master")
endif()
message(STATUS "Tracking ValidatorKeys branch: ${current_branch}")
# Own the install destination below rather than relying on another module
# having pulled this in first.
include(GNUInstallDirs)
# Pinned to an exact commit, not a branch: the tool ships inside our
# packages, so the same xrpld version must always package the same
# validator-keys. Bump this deliberately.
set(validator_keys_commit "4c0fb75eec9601c711645998c904507e87e910ae")
message(STATUS "Using ValidatorKeys commit: ${validator_keys_commit}")
FetchContent_Declare(
validator_keys
GIT_REPOSITORY https://github.com/ripple/validator-keys-tool.git
GIT_TAG "${current_branch}"
GIT_TAG "${validator_keys_commit}"
)
FetchContent_MakeAvailable(validator_keys)
# The tool's own CMakeLists excludes the target from 'all' when it is built
# as a subproject. Undo that, so validator_keys=ON really does build it.
set_target_properties(
validator-keys
PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
EXCLUDE_FROM_ALL OFF
EXCLUDE_FROM_DEFAULT_BUILD OFF
)
# We ship this binary, so like xrpld it must not keep the Nix store's ELF
# loader, or it cannot run on the target distro at all.
patch_nix_binary(validator-keys)
configure_file(
"${validator_keys_SOURCE_DIR}/LICENSE"
"${CMAKE_BINARY_DIR}/validator-keys-LICENSE"
COPYONLY
)
install(TARGETS validator-keys RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()

View File

@@ -12,7 +12,7 @@
"protobuf/6.33.5#ff253ead763bd8d9904a52979cd21e81%1782392410.233933",
"openssl/3.6.3#f806de8933e3bf6f01016c6a888cee2e%1783945160.863288",
"nudb/2.0.9#11149c73f8f2baff9a0198fe25971fc7%1782392402.297166",
"mpt-crypto/0.4.0-rc4#ffdba12f2332357f0d8b0ae944cfff52%1784138702.932355",
"mpt-crypto/1.0.2#b313cef0c1a493eb970ad185b2e9bab7%1784285108.866483",
"lz4/1.10.0#982d9b673900f665a1da109e09c17cab%1782392402.164188",
"libiconv/1.17#9923bc6dc6f106646d6967e0039a5ada%1782392792.775744",
"libbacktrace/cci.20210118#a7691bfccd8caaf66309df196790a5a1%1782392402.420732",
@@ -20,13 +20,11 @@
"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",
"bzip2/1.0.8#c470882369c2d95c5c77e970c0c7e321%1782392402.296732",
"boost/1.91.0#ea540ca2133d831b560036aa24dece3c%1782392419.475605",
"benchmark/1.9.5#b885dc73ad67b40a55d45684d1c88ad1%1782736613.864841",
"abseil/20250127.0#9ef01c1451a8340f9022e46238c0fbb6%1783945159.651047"
],
"build_requires": [
@@ -35,7 +33,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#1727f439cf74e83826ec96d0b4904eee%1784541921.659",
"m4/1.4.19#34c4bbc3eeebe98ca6edf2f52d602e7d%1777282960.259",
"cmake/4.3.3#840cf00ea09777e05c2050a50a82c722%1782392418.696091",
"b2/5.4.2#ffd6084a119587e70f11cd45d1a386e2%1782392402.624226",
"automake/1.16.5#b91b7c384c3deaa9d535be02da14d04f%1755524470.56",

View File

@@ -5,13 +5,6 @@
{% 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 }}
@@ -25,39 +18,10 @@ 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. #}
{# Instead it hand-rolls the compiler for user-config.jam, #}
{# and its fallback probes a version-suffixed binary (e.g. `g++-15`) before plain `g++`. #}
{# Inside the Nix shell the wrapper only provides `g++`/`gcc` (no `-15` suffix), #}
{# so on a host that also has a system `g++-15` the probe escapes Nix #}
{# and picks the system compiler, which is mismatched with the Nix libraries #}
{# and breaks the build (e.g. Boost.Stacktrace link checks fail). #}
{# Pinning the executables here short-circuits that probe so Boost (and the rest of the toolchain) #}
{# resolve the same compiler. #}
{# Not part of the package ID, so binaries stay shareable. #}
{% if os != "Windows" %}
{% set cc_exe = {"gcc": "gcc", "clang": "clang", "apple-clang": "clang"}.get(compiler) %}
{% set cxx_exe = {"gcc": "g++", "clang": "clang++", "apple-clang": "clang++"}.get(compiler) %}
tools.build:compiler_executables={'c':'{{ cc_exe }}','cpp':'{{ cxx_exe }}'}
{% endif %}
{# By default, Conan tries to reuse binaries built with different cppstd versions. #}
{# We want to avoid that to improve reproduceability, so we add the cppstd version to the package ID. #}
{# 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

@@ -15,7 +15,6 @@ class Xrpl(ConanFile):
settings = "os", "compiler", "build_type", "arch"
options = {
"assertions": [True, False],
"benchmark": [True, False],
"coverage": [True, False],
"fPIC": [True, False],
"jemalloc": [True, False],
@@ -29,7 +28,6 @@ class Xrpl(ConanFile):
requires = [
"ed25519/2015.03",
"fast_float/8.2.10",
"grpc/1.81.1",
"libarchive/3.8.7",
"nudb/2.0.9",
@@ -48,7 +46,6 @@ class Xrpl(ConanFile):
default_options = {
"assertions": False,
"benchmark": True,
"coverage": False,
"fPIC": True,
"jemalloc": False,
@@ -132,14 +129,12 @@ class Xrpl(ConanFile):
self.options["boost"].without_cobalt = True
def requirements(self):
if self.options.benchmark:
self.requires("benchmark/1.9.5")
self.requires("boost/1.91.0", force=True, transitive_headers=True)
self.requires("date/3.0.4", transitive_headers=True)
if self.options.jemalloc:
self.requires("jemalloc/5.3.1")
self.requires("lz4/1.10.0", force=True)
self.requires("mpt-crypto/0.4.0-rc4", transitive_headers=True)
self.requires("mpt-crypto/1.0.2", transitive_headers=True)
self.requires("protobuf/6.33.5", force=True)
if self.options.rocksdb:
self.requires("rocksdb/10.5.1")
@@ -167,7 +162,6 @@ class Xrpl(ConanFile):
def generate(self):
tc = CMakeToolchain(self)
tc.variables["tests"] = self.options.tests
tc.variables["benchmark"] = self.options.benchmark
tc.variables["assert"] = self.options.assertions
tc.variables["coverage"] = self.options.coverage
tc.variables["jemalloc"] = self.options.jemalloc
@@ -212,7 +206,6 @@ 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,10 +38,8 @@ 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 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.
- **Linux**: `nix develop` gives you a shell with all the tooling necessary to
develop xrpld and with GCC 15.2 (also provided by Nix). There are no caveats.
- **macOS**: `nix develop` gives you a full environment too, 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
@@ -65,16 +63,8 @@ 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`.
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.
The `.#gcc` and `.#clang` shells provide the same GCC and Clang versions used in CI
(pinned in [`nix/packages.nix`](../../nix/packages.nix)).
Use `nix flake show` to see all the available development shells.
Use `nix develop .#no-compiler` to use the compiler from your system.
@@ -82,18 +72,14 @@ Use `nix develop .#no-compiler` to use the compiler from your system.
### Example Usage
```bash
# Use GCC same toolchain as CI (custom glibc on Linux)
# Use GCC (same version as CI)
nix develop .#gcc
# Use Clang same toolchain as CI (custom glibc on Linux)
# Use Clang (same version as CI)
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
@@ -124,10 +110,6 @@ 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.
@@ -154,14 +136,6 @@ 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,78 +3,6 @@
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:

23
flake.lock generated
View File

@@ -36,28 +36,7 @@
"root": {
"inputs": {
"nixpkgs": "nixpkgs",
"nixpkgs-custom-glibc": "nixpkgs-custom-glibc",
"rust-overlay": "rust-overlay"
}
},
"rust-overlay": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1784611586,
"narHash": "sha256-OfqgY+0hp/zseZB7uyH0U8kIDPS4scZZCyAurEplvG0=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "14f58845249f3552a89b07772626b8d3c632fa86",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
"nixpkgs-custom-glibc": "nixpkgs-custom-glibc"
}
}
},

View File

@@ -10,25 +10,12 @@
url = "github:NixOS/nixpkgs/9cd98386a38891d1074fc18036b842dc4416f562";
flake = false;
};
# Pinned Rust toolchains, delivered from the Nix store. Lets the Nix CI
# image and dev shell honour the single `rust-toolchain.toml` pin (shared
# with the rustup-based non-Nix runners) while staying hermetic — the
# toolchain lands in the image's Nix closure and is locked by flake.lock.
rust-overlay = {
url = "github:oxalica/rust-overlay";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs =
{
nixpkgs,
nixpkgs-custom-glibc,
rust-overlay,
...
}:
{ nixpkgs, nixpkgs-custom-glibc, ... }:
let
forEachSystem = import ./nix/utils.nix { inherit nixpkgs nixpkgs-custom-glibc rust-overlay; };
forEachSystem = import ./nix/utils.nix { inherit nixpkgs nixpkgs-custom-glibc; };
in
{
devShells = forEachSystem (import ./nix/devshell.nix);

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,7 +11,6 @@
#include <limits>
#include <stdexcept>
#include <string>
#include <string_view>
#include <type_traits>
#include <vector>
@@ -252,11 +251,4 @@ 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

@@ -74,20 +74,13 @@ public:
using shared_pointer_type = SharedPointerType;
public:
/**
* @param cacheHardCap When positive, a hard upper bound on the number of
* strongly-cached entries, enforced by demoting the approximately
* oldest entry whenever growth would exceed it. 0 disables the cap
* (the periodic sweep alone bounds the cache).
*/
TaggedCache(
std::string const& name,
int size,
clock_type::duration expiration,
clock_type& clock,
beast::Journal journal,
beast::insight::Collector::ptr const& collector = beast::insight::NullCollector::make(),
int cacheHardCap = 0);
beast::insight::Collector::ptr const& collector = beast::insight::NullCollector::make());
public:
/**
@@ -364,13 +357,6 @@ private:
using cache_type = hardened_partitioned_hash_map<key_type, Entry, Hash, KeyEqual>;
// Bounded approximate-LRU eviction from a single partition. Keeps the
// strong-entry count at/below cacheHardCap_ as new entries are inserted, so
// a burst can't drive the cache past its RAM budget between timer sweeps.
// No-op unless cacheHardCap_ > 0 (opt-in); caller holds mutex_.
void
evictForHardCap(cache_type::map_type& partition, cache_type::map_type::iterator const& keep);
[[nodiscard]] std::thread
sweepHelper(
clock_type::time_point const& whenExpire,
@@ -404,23 +390,8 @@ private:
// Desired maximum cache age
clock_type::duration const targetAge_;
// Hard upper bound on strongly-cached entries, enforced by
// evictForHardCap whenever the strong count grows (fresh inserts and
// weak-to-strong revivals). 0 disables it (sweep-only sizing).
int const cacheHardCap_;
// Total hard-cap evictions (under mutex_); the first marks saturation
// onset for logging.
std::uint64_t hardCapEvictions_{0};
// Number of items cached
int cacheCount_{0};
// Rotating bucket cursor for evictForHardCap so successive over-cap
// evictions sweep the whole partition (CLOCK hand) instead of repeatedly
// sampling the head buckets. Advanced under mutex_.
std::size_t evictHand_{0};
cache_type cache_; // Hold strong reference to recent objects
std::uint64_t hits_{0};
std::uint64_t misses_{0};

View File

@@ -57,8 +57,7 @@ inline TaggedCache<
clock_type::duration expiration,
clock_type& clock,
beast::Journal journal,
beast::insight::Collector::ptr const& collector,
int cacheHardCap)
beast::insight::Collector::ptr const& collector)
: journal_(journal)
, clock_(clock)
, stats_(
@@ -68,7 +67,6 @@ inline TaggedCache<
, name_(name)
, targetSize_(size)
, targetAge_(expiration)
, cacheHardCap_(cacheHardCap)
{
}
@@ -221,102 +219,6 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
return true;
}
template <
class Key,
class T,
bool IsKeyCache,
class SharedWeakUnionPointer,
class SharedPointerType,
class Hash,
class KeyEqual,
class Mutex>
inline void
TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash, KeyEqual, Mutex>::
evictForHardCap(cache_type::map_type& partition, cache_type::map_type::iterator const& keep)
{
// Caller holds mutex_. Only value caches carry strong/weak entries; key
// caches never enable the hard cap, so this is a no-op for them.
if constexpr (!IsKeyCache)
{
std::size_t const bucketCount = partition.bucket_count();
if (bucketCount == 0)
return;
// Approximate LRU with bounded work per call: sample a window of
// strong entries starting at the rotating bucket cursor and demote
// the oldest, repeating until the count is back under the cap or the
// demotion budget is spent. Growth paths raise the count by one at a
// time, so the budget lets eviction catch up without stalling them.
constexpr int kEvictSampleBudget = 64;
constexpr int kMaxDemotionsPerCall = 8;
std::size_t const maxBuckets = std::min<std::size_t>(bucketCount, 4 * kEvictSampleBudget);
for (int demotions = 0; cacheCount_ > cacheHardCap_ && demotions < kMaxDemotionsPerCall;
++demotions)
{
int sampled = 0;
std::size_t bucketsWalked = 0;
key_type oldestKey{};
bool haveOldest = false;
clock_type::time_point oldestAccess{};
std::size_t b = evictHand_ % bucketCount;
while (sampled < kEvictSampleBudget && bucketsWalked < maxBuckets)
{
for (auto lit = partition.begin(b); lit != partition.end(b); ++lit)
{
if (lit->first == keep->first || lit->second.isWeak())
continue;
if (!haveOldest || lit->second.lastAccess < oldestAccess)
{
oldestAccess = lit->second.lastAccess;
oldestKey = lit->first;
haveOldest = true;
}
if (++sampled >= kEvictSampleBudget)
break;
}
b = (b + 1) % bucketCount;
++bucketsWalked;
}
evictHand_ = b; // resume the scan here on the next over-cap call
if (!haveOldest)
{
JLOG(journal_.debug()) << name_ << ": over hard cap " << cacheHardCap_
<< " but eviction sample found no strong entry to demote";
return;
}
auto oldest = partition.find(oldestKey);
if (oldest == partition.end() || oldest == keep || oldest->second.isWeak())
return;
if (oldest->second.ptr.useCount() == 1)
{
// Sole owner: release entirely.
partition.erase(oldest);
}
else
{
// Others hold it: keep it weakly tracked.
oldest->second.ptr.convertToWeak();
}
--cacheCount_;
// First eviction marks saturation onset; then a heartbeat every
// 100k to avoid flooding.
++hardCapEvictions_;
if (hardCapEvictions_ == 1 || hardCapEvictions_ % 100000 == 0)
{
JLOG(journal_.warn()) << name_ << ": hard-cap eviction #" << hardCapEvictions_
<< " (cap " << cacheHardCap_ << ", strong " << cacheCount_
<< ") - cache saturated, growth now evicts";
}
}
}
}
template <
class Key,
class T,
@@ -458,17 +360,11 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
if (cit == cache_.end())
{
auto const emplacedIt = cache_
.emplace(
std::piecewise_construct,
std::forward_as_tuple(key),
std::forward_as_tuple(clock_.now(), data))
.first;
cache_.emplace(
std::piecewise_construct,
std::forward_as_tuple(key),
std::forward_as_tuple(clock_.now(), data));
++cacheCount_;
// The just-inserted entry is the newest; evictForHardCap skips it
// and drops the oldest in its partition.
if (cacheHardCap_ > 0 && cacheCount_ > cacheHardCap_)
evictForHardCap(*emplacedIt.ait, emplacedIt.mit);
return false;
}
@@ -519,15 +415,11 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
}
++cacheCount_;
if (cacheHardCap_ > 0 && cacheCount_ > cacheHardCap_)
evictForHardCap(*cit.ait, cit.mit);
return true;
}
entry.ptr = data;
++cacheCount_;
if (cacheHardCap_ > 0 && cacheCount_ > cacheHardCap_)
evictForHardCap(*cit.ait, cit.mit);
return false;
}
@@ -837,8 +729,6 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
{
// independent of cache size, so not counted as a hit
++cacheCount_;
if (cacheHardCap_ > 0 && cacheCount_ > cacheHardCap_)
evictForHardCap(*cit.ait, cit.mit);
entry.touch(clock_.now());
return entry.ptr.getStrong();
}

View File

@@ -41,6 +41,35 @@
namespace xrpl {
namespace base64 {
/**
* Returns the maximum number of characters needed to base64-encode @p nBytes bytes.
*
* @param nBytes Number of input bytes.
* @return Size of the encoded string, including padding.
*/
constexpr std::size_t
encodedSize(std::size_t const nBytes)
{
return 4 * ((nBytes + 2) / 3);
}
/**
* Returns the maximum number of bytes a base64 string of @p numChars characters
* decodes to.
*
* @param numChars Number of base64 characters.
* @return Upper bound on the number of decoded bytes.
*/
constexpr std::size_t
decodedSize(std::size_t const numChars)
{
return ((numChars / 4) * 3) + 2;
}
} // namespace base64
std::string
base64Encode(std::uint8_t const* data, std::size_t len);

View File

@@ -5,7 +5,6 @@
#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>
constexpr bool
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;
constexpr bool
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;
constexpr bool
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;
constexpr bool
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;
constexpr bool
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>
constexpr bool
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>
constexpr Out
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>
constexpr Out
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 IdentifierList = std::vector<std::string>;
using identifier_list = std::vector<std::string>;
int majorVersion;
int minorVersion;
int patchVersion;
IdentifierList preReleaseIdentifiers;
IdentifierList metaData;
identifier_list preReleaseIdentifiers;
identifier_list 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,20 +295,6 @@ 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

@@ -22,13 +22,11 @@ struct Sections
static constexpr auto kIoWorkers = "io_workers";
static constexpr auto kIps = "ips";
static constexpr auto kIpsFixed = "ips_fixed";
static constexpr auto kLedgerCacheAge = "ledger_cache_age";
static constexpr auto kLedgerFetchSize = "ledger_fetch_size";
static constexpr auto kLedgerHistory = "ledger_history";
static constexpr auto kLedgerReplay = "ledger_replay";
static constexpr auto kLedgerTxTables = "ledger_tx_tables";
static constexpr auto kMaxSubscriptionsPerConnection = "max_subscriptions_per_connection";
static constexpr auto kMaxTransactions = "max_transactions";
static constexpr auto kMemoryLimit = "memory_limit";
static constexpr auto kNetworkId = "network_id";
static constexpr auto kNetworkQuorum = "network_quorum";
static constexpr auto kNodeDatabase = "node_db";
@@ -66,7 +64,6 @@ struct Sections
static constexpr auto kSslVerifyFile = "ssl_verify_file";
static constexpr auto kSweepInterval = "sweep_interval";
static constexpr auto kTransactionQueue = "transaction_queue";
static constexpr auto kTreeCacheAge = "tree_cache_age";
static constexpr auto kValidationSeed = "validation_seed";
static constexpr auto kValidatorKeys = "validator_keys";
static constexpr auto kValidatorKeyRevocation = "validator_key_revocation";
@@ -122,7 +119,9 @@ struct Keys
static constexpr auto kLogInterval = "log_interval";
static constexpr auto kMaxDivergedTime = "max_diverged_time";
static constexpr auto kMaxLedgerCountsToStore = "max_ledger_counts_to_store";
static constexpr auto kMaxTrustedCount = "max_trusted_count";
static constexpr auto kMaxUnknownTime = "max_unknown_time";
static constexpr auto kMaxUntrustedCount = "max_untrusted_count";
static constexpr auto kMaximumTxnInLedger = "maximum_txn_in_ledger";
static constexpr auto kMaximumTxnPerAccount = "maximum_txn_per_account";
static constexpr auto kMemoryLevel = "memory_level";

View File

@@ -15,12 +15,12 @@
namespace xrpl {
// Forward declarations
namespace node_store {
namespace NodeStore {
class Database;
} // namespace node_store
namespace resource {
} // namespace NodeStore
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 node_store::Database&
virtual NodeStore::Database&
getNodeStore() = 0;
virtual SHAMapStore&

View File

@@ -623,7 +623,6 @@ 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;
@@ -688,7 +687,6 @@ 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

@@ -263,11 +263,10 @@ constructLoanState(
Number const& principalOutstanding,
Number const& managementFeeOutstanding);
// Overload of constructLoanState() that reads the three tracked fields
// directly from a Loan ledger object, which always holds rounded values,
// rather than taking them as separate Number arguments.
// Constructs a valid LoanState object from a Loan object, which always has
// rounded values
LoanState
constructLoanState(SLE::const_ref loan);
constructRoundedLoanState(SLE::const_ref loan);
Number
computeManagementFee(
@@ -286,77 +285,6 @@ 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

@@ -2,7 +2,6 @@
#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>
@@ -108,19 +107,4 @@ 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::node_store {
namespace xrpl::NodeStore {
/**
* A backend used for the NodeStore.
@@ -163,4 +163,4 @@ public:
fdRequired() const = 0;
};
} // namespace xrpl::node_store
} // namespace xrpl::NodeStore

View File

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

View File

@@ -9,7 +9,7 @@
#include <memory>
#include <string>
namespace xrpl::node_store {
namespace xrpl::NodeStore {
/* 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<node_store::Backend>&& newBackend,
std::unique_ptr<NodeStore::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::node_store
} // namespace xrpl::NodeStore

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -5,7 +5,7 @@
#include <memory>
#include <vector>
namespace xrpl::node_store {
namespace xrpl::NodeStore {
// 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::node_store
} // namespace xrpl::NodeStore

View File

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

View File

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

View File

@@ -16,7 +16,7 @@
#include <mutex>
#include <string>
namespace xrpl::node_store {
namespace xrpl::NodeStore {
class DatabaseRotatingImp : public DatabaseRotating
{
@@ -41,7 +41,7 @@ public:
void
rotate(
std::unique_ptr<node_store::Backend>&& newBackend,
std::unique_ptr<NodeStore::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::node_store
} // namespace xrpl::NodeStore

View File

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

View File

@@ -12,7 +12,7 @@
#include <memory>
#include <stdexcept>
namespace xrpl::node_store {
namespace xrpl::NodeStore {
/**
* 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::node_store::EncodedBlob::EncodedBlob : non-null input");
XRPL_ASSERT(obj, "xrpl::NodeStore::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::node_store::EncodedBlob::~EncodedBlob : valid payload "
"xrpl::NodeStore::EncodedBlob::~EncodedBlob : valid payload "
"pointer");
if (ptr_ != payload_.data())
@@ -114,4 +114,4 @@ public:
}
};
} // namespace xrpl::node_store
} // namespace xrpl::NodeStore

View File

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

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::node_store {
namespace xrpl::NodeStore {
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, VarintTraits<std::size_t>::kMax> vi{};
std::array<std::uint8_t, varint_traits<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, VarintTraits<std::size_t>::kMax> vi{};
std::array<std::uint8_t, varint_traits<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 = node_store::lz4Compress(in, inSize, [&p, &vn, &bf](std::size_t n) {
auto const lzr = NodeStore::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::node_store
} // namespace xrpl::NodeStore

View File

@@ -6,25 +6,25 @@
#include <cstdint>
#include <type_traits>
namespace xrpl::node_store {
namespace xrpl::NodeStore {
// 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;
// Metafunction to return largest
// Metafuncton to return largest
// possible size of T represented as varint.
// T must be unsigned
template <class T, bool = std::is_unsigned_v<T>>
struct VarintTraits;
struct varint_traits;
template <class T>
struct VarintTraits<T, true>
struct varint_traits<T, true>
{
explicit VarintTraits() = default;
explicit varint_traits() = 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::node_store
} // namespace xrpl::NodeStore

View File

@@ -1,163 +0,0 @@
#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

@@ -1,179 +0,0 @@
#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

@@ -1,46 +0,0 @@
#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

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