Compare commits

...

175 Commits

Author SHA1 Message Date
Vito
8327f7d4f7 fix: clang-tidy
Address the diagnostics surfaced by the PR clang-tidy job:

- RippleStateHelpers.cpp / TokenHelpers.cpp: mark the STNumber.h
  include with `IWYU pragma: keep`. The header is needed for the
  ValueProxy<STNumber> assignments to sfDust but misc-include-cleaner
  reports it as unused because the type only appears as a template
  parameter of the SLE proxy.
- TokenHelpers.cpp: replace `XRPL_ASSERT(false, ...)` with UNREACHABLE
  in the pre-Lend11 DustSplit guard (misc-static-assert).
- DustSplitArithmetic_test.cpp: drop unused test-helper includes,
  add the direct headers surfaced by misc-include-cleaner
  (contract.h, ApplyView.h, <stdexcept>, <string>, <utility>),
  add const on locals, use designated initializers for
  HolderCtx / TransitCtx / MultiSendCtx, drop std::move on
  trivially-copyable PrettyAsset, make setup* methods static,
  add braces around the sender/receiver leg dispatch, fix an
  argument-comment name mismatch, and rename every testG*_*
  method to camelBack (readability-identifier-naming).
2026-08-14 04:47:41 +02:00
Vito
c889b4eb5b Merge branch 'tapanito/vault-dust-sfield' into tapanito/vault-dust-primitive 2026-08-13 18:44:06 +02:00
Vito
5d00a85872 Merge branch 'tapanito/vault-add-assets-helper' into tapanito/vault-dust-sfield 2026-08-13 18:43:47 +02:00
Vito
2cc42ea8b8 fix: Regenerate ledger entry autogen for STNumber.h include
The LedgerEntry.h.mako update in this PR emits `#include
<xrpl/protocol/STNumber.h>` when any field is a NUMBER type, but the
regenerated headers for the three existing NUMBER-carrying ledger
entries (Loan, LoanBroker, Vault) were not checked in. This restores
byte parity with the codegen output that check-autogen enforces.
2026-08-13 18:43:10 +02:00
Vito
6d5564afd5 fix: Include STNumber.h in helpers that read sfDust
RippleStateHelpers.cpp and TokenHelpers.cpp instantiate
STObject::at<STNumber>() through sle->at(sfDust). The autogen
RippleState.h pulls STNumber.h transitively but neither of these
translation units includes RippleState.h, so STNumber was only
forward-declared and the templates failed to instantiate (build break
on all platforms).
2026-08-13 18:42:09 +02:00
Vito
2c3a52e697 fix: Drop unused instrumentation.h include in LoanManage.cpp
Silences the clang-tidy misc-include-cleaner error introduced by an
earlier merge from tapanito/fix-lending-cross-scale.
2026-08-13 18:41:17 +02:00
Vito
4edefa32e4 fix: remove bad tests 2026-08-13 14:18:02 +02:00
Vito Tumas
ac7a66d940 Merge branch 'tapanito/vault-dust-sfield' into tapanito/vault-dust-primitive 2026-08-13 14:15:53 +02:00
Vito Tumas
5c2fc5082c Merge branch 'tapanito/vault-add-assets-helper' into tapanito/vault-dust-sfield 2026-08-13 14:15:22 +02:00
Vito
81c94622f7 test: Add DustSplitCreditPath suite
Three trust-line-layer tests for the DustSplit primitive and its
credit-path threading:

- Ordinary payments (nullptr policy) never acquire sfDust — the
  feature-gated code path is inert without a caller-supplied DustSplit.
- Plain accountSend across a line seeded with non-zero sfDust must
  preserve that reservoir byte-for-byte; the nullptr-policy path is
  dust-agnostic in both directions.
- removeEmptyHolding returns tecHAS_OBLIGATIONS while sfDust != 0 and
  tesSUCCESS once sfDust is zero, pinning both sides of the deletion
  guard.

Uses only the trust-line layer (Sandbox-level SLE mutation +
accountSend/removeEmptyHolding). No vault_dust:: consumer is exercised
here — that lands in the follow-up overlay PR.
2026-08-13 14:13:45 +02:00
Vito
f27559ad97 feat: Add DustSplit primitive and thread it through the IOU credit path
Introduces DustSplit, a per-leg dust policy struct threaded through
directSendNoFeeIOU / accountSend / accountSendMulti / doWithdraw, plus
the read-side creditBalanceExact helper.

DustSplit models an IOU payment as two independent trust-line touches
(sender leg, receiver leg). Each leg carries an optional LegPolicy in
one of two modes:

- Override: caller supplies the target STAmount scale; the credit path
  computes the extended balance (sfBalance + sfDust) in the leg's
  non-issuer party's terms, applies the delta, and re-splits at the
  requested scale. Any stranded sfDust above one quantum at the new
  scale is promoted into sfBalance as part of the same re-split, so
  scale-refinement is fold-in-place.
- Drain (sender-leg only): folds all sender-line sfDust into the
  outgoing transfer, leaving sfBalance == 0 and sfDust == 0. Used for
  terminal removals.

Reports back the observed per-leg deltas (balanceDelta and signed
dustDelta) in the leg-party's own sign convention, letting the caller
reconcile its own bookkeeping without re-reading the trust line.

directSendNoFeeIOU is the single site where sfDust writes happen.
Feature-gated: directSendNoFeeIOU asserts featureLendingProtocolV1_1
on any non-empty DustSplit; without the amendment the classic code
path runs unchanged.

creditBalanceExact reads the extended balance in the holder's terms;
classic accountHolds remains STAmount-only.

No consumers wired in yet; that lands in follow-ups.
2026-08-13 14:11:06 +02:00
Vito
9445d56754 test: Add RippleStateSfDust suite for the sfDust field
Two protocol-level tests for the sfDust field:
- Absent sfDust reads as zero on an untouched trust line (SoeDefault
  read path).
- SoeDefault byte-encoding contract: absent and explicit-zero encodings
  are byte-identical, so a pre-amendment ledger and a post-amendment
  ledger stay hash-compatible for any RippleState that has never carried
  non-zero dust.

Both tests use only SLE / trust-line primitives — no DustSplit and no
vault_dust:: consumer (both land in follow-up PRs).

Also picks up 'reserialise*' in cspell, used in the byte-compat test's
docstring.
2026-08-13 14:11:05 +02:00
Vito
28603cf40e test: Add RippleStateSfDust suite for the sfDust field
Two protocol-level tests for the sfDust field:
- Absent sfDust reads as zero on an untouched trust line (SoeDefault
  read path).
- SoeDefault byte-encoding contract: absent and explicit-zero encodings
  are byte-identical, so a pre-amendment ledger and a post-amendment
  ledger stay hash-compatible for any RippleState that has never carried
  non-zero dust.

Both tests use only SLE / trust-line primitives — no DustSplit and no
vault_dust:: consumer (both land in follow-up PRs).

Also picks up 'reserialise*' in cspell, used in the byte-compat test's
docstring.
2026-08-13 14:11:05 +02:00
Vito
f04d065099 feat: Add sfDust field on RippleState
Introduces the sfDust NUMBER field (id 18) on ltRIPPLE_STATE, a
sub-quantum residual for the trust-line credit path. Together with
sfBalance it forms the trust line's extended balance.

kSmdNeedsAsset is deliberately omitted: that flag rounds the field to
the asset's representable precision via associateAsset(), which is the
opposite of sfDust's purpose (it exists to hold value finer than that
precision).

No writer or consumer of the field yet; that lands in follow-ups.

Additive-only:
- New sfields.macro entry with rationale
- ltRIPPLE_STATE gains an SoeDefault sfDust slot
- Regenerated RippleState.h getters/setters + hasDust
- LedgerEntry.h.mako gains a conditional STNumber.h include so any
  NUMBER-bearing ledger entry pulls STNumber directly (avoids
  transitively relying on STLedgerEntry.h)
- RippleStateTests round-trip and nullopt coverage for sfDust
- .cspell.config.yaml picks up 'recognise*'/'renormalise*' used in
  follow-up docs and code
2026-08-13 14:11:05 +02:00
Vito
44f08df449 Merge remote-tracking branch 'origin/tapanito/fix-lending-cross-scale' into tapanito/vault-add-assets-helper 2026-08-13 14:09:17 +02:00
Vito
840a41f880 refactor: clean up VaultHelpers 2026-08-13 14:08:14 +02:00
Vito
8874a97b7f fix: clang-tidy 2026-08-13 14:07:51 +02:00
Vito
58e459a4a0 fix: improve docs 2026-08-13 13:58:15 +02:00
Vito
c57709b17a fix: clang-tidy 2026-08-13 11:50:54 +02:00
Vito
cf1a551a97 Merge branch 'tapanito/fix-lending-cross-scale' into tapanito/vault-add-assets-helper
# Conflicts:
#	include/xrpl/ledger/helpers/VaultHelpers.h
#	src/libxrpl/ledger/helpers/VaultHelpers.cpp
#	src/libxrpl/tx/transactors/lending/LoanManage.cpp
#	src/libxrpl/tx/transactors/lending/LoanPay.cpp
2026-08-13 11:38:05 +02:00
Vito
17c9a87070 test: Add RippleStateSfDust suite for the sfDust field
Two protocol-level tests for the sfDust field:
- Absent sfDust reads as zero on an untouched trust line (SoeDefault
  read path).
- SoeDefault byte-encoding contract: absent and explicit-zero encodings
  are byte-identical, so a pre-amendment ledger and a post-amendment
  ledger stay hash-compatible for any RippleState that has never carried
  non-zero dust.

Both tests use only SLE / trust-line primitives — no DustSplit and no
vault_dust:: consumer (both land in follow-up PRs).

Also picks up 'reserialise*' in cspell, used in the byte-compat test's
docstring.
2026-08-13 11:03:07 +02:00
Vito
74102450a8 Merge branch 'develop' into tapanito/fix-lending-cross-scale 2026-08-13 10:40:08 +02:00
Jingchen
8e9b1791c5 feat: Add a new closed ended vault to extend SAV (#7921)
Co-authored-by: Vito Tumas <5780819+Tapanito@users.noreply.github.com>
2026-08-12 17:07:43 +00:00
Vito
f012e3d305 feat: Add sfDust field on RippleState
Introduces the sfDust NUMBER field (id 18) on ltRIPPLE_STATE, a
sub-quantum residual for the trust-line credit path. Together with
sfBalance it forms the trust line's extended balance.

kSmdNeedsAsset is deliberately omitted: that flag rounds the field to
the asset's representable precision via associateAsset(), which is the
opposite of sfDust's purpose (it exists to hold value finer than that
precision).

No writer or consumer of the field yet; that lands in follow-ups.

Additive-only:
- New sfields.macro entry with rationale
- ltRIPPLE_STATE gains an SoeDefault sfDust slot
- Regenerated RippleState.h getters/setters + hasDust
- LedgerEntry.h.mako gains a conditional STNumber.h include so any
  NUMBER-bearing ledger entry pulls STNumber directly (avoids
  transitively relying on STLedgerEntry.h)
- RippleStateTests round-trip and nullopt coverage for sfDust
- .cspell.config.yaml picks up 'recognise*'/'renormalise*' used in
  follow-up docs and code
2026-08-12 18:33:27 +02:00
Ayaz Salikhov
946827b9bd build: Respect lld linker if it gets auto-selected (#8011) 2026-08-12 12:11:28 -04:00
Vito Tumas
91360c5126 test: Fix LoanBatch broker cover rates and schedule overflow (#7967) 2026-08-12 12:11:28 -04:00
Timur Yalymov
af36890c11 test: Verify private-vault DEX permissions survive domain loss (#7937) 2026-08-12 12:11:28 -04:00
Timur Yalymov
1281c7a222 refactor: Drop unnecessary associateAsset calls from loan delete paths (#7986)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-12 12:10:17 -04:00
Copilot
153b7839a7 refactor: Replace boost::filesystem with std::filesystem across the codebase (#7012)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: mvadari <8029314+mvadari@users.noreply.github.com>
Co-authored-by: Mayukha Vadari <mvadari@ripple.com>
Co-authored-by: Mayukha Vadari <mvadari@gmail.com>
Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: mathbunnyru <12270691+mathbunnyru@users.noreply.github.com>
2026-08-12 13:40:39 +00:00
Vito Tumas
33f839c7c7 Merge branch 'develop' into tapanito/fix-lending-cross-scale 2026-08-12 13:29:45 +02:00
Gregory Tsipenyuk
26cc683ec1 fix: Assorted MPT/DEX fixes (#7299)
Co-authored-by: Valentin Balaschenko <13349202+vlntb@users.noreply.github.com>
2026-08-11 18:15:51 +00:00
Mayukha Vadari
6ca2fb84d4 refactor: Replace Boost trim and to_lower with libxrpl helpers (#7995) 2026-08-11 18:15:35 +00:00
Vito
c12e4730ae test: Multi-loan drift regression sensor for fixCleanup3_4_0
Adds testMultiLoanDefaultDriftFixVsLegacy which runs the same
drift-inducing scenario (3 loans, different scales, partial payments,
impairment, then default) under both !fixCleanup3_4_0 and
fixCleanup3_4_0 and confirms both paths leave the vault
invariant-safe.

Empirically the two branches produce identical post-default state
because computeLoanProperties clamps loanScale >= vaultScale (via
std::max(minimumScale, amount.exponent())), so the pre-amendment
roundToAsset(vaultDefaultAmount, vaultScale, Down) is a no-op for
well-formed loans. The dust-reconciliation branch this test guards
against is doubly-defensive code — reachable only from a corrupted
ledger, not a valid transaction sequence.

The test acts as a regression sensor: any future change that breaks
the invariant on either branch (or lets them diverge) will surface
here.
2026-08-11 18:15:55 +02:00
Vito
9f4cdb80cd fix: Eliminate cross-scale arithmetic in LoanPay::doApply
Gated behind fixCleanup3_4_0. Pre-amendment, the payment path used the
same cross-scale pattern that `LoanManage::defaultLoan` addressed:
`totalPaidToVault` was rounded down to `vaultScale` before being applied
to `sfAssetsAvailable`, while `assetsTotalDelta` (`valueChange` for
accrual, `interestPaid` for cash-basis) was applied at the finer loan
scale. The `sfAssetsAvailable <= sfAssetsTotal` invariant was only
defended by an assertion after the fact.

Under the fix, drop the `roundToAsset(..., vaultScale, Downward)` step
and apply the raw `totalPaidToVault` to both the ledger update and the
cash transfer via `accountSendMulti`. The pseudo-account balance and
`sfAssetsAvailable` therefore land on the same STAmount value without
an intermediate scale reduction.

For integral assets this is a no-op (the removed rounding was already a
no-op there). For non-integral IOUs, the vault receives the full raw
payment (up to 1 vaultScale ULP more than pre-amendment) and the
existing `tecPRECISION_LOSS` / `tecINTERNAL` post-checks are no longer
needed as safety nets against an arithmetic-induced Available > Total.

`LoanPay_test` now runs the amendment-sensitive tests under both
branches by adding `fixCleanup3_4_0` to the `amendmentCombinations`
matrix, matching the sibling change to `LoanRounding_test`.
2026-08-11 18:15:55 +02:00
Vito
95850644a9 fix: Eliminate cross-scale arithmetic in LoanManage::defaultLoan
Gated behind fixCleanup3_4_0. Pre-amendment, `defaultLoan` mutated
`sfAssetsTotal` and `sfAssetsAvailable` with values at different scales --
`vaultDefaultAmount` rounded down to `vaultScale`, but `defaultCovered`
kept at the finer loan scale. That asymmetry could leave
`sfAssetsAvailable > sfAssetsTotal` from the arithmetic alone, and was
patched by a dust-reconciliation branch that snapped `Total` up to
`Available`. That snap effectively minted phantom assets on `Total`
(see `LoanRounding_test::testDustManipulation`).

Under the fix, the vault-side update is composed from two well-defined
STAmount operations at the vault asset's own scale:

  (1) Write-off: `sfAssetsTotal -= totalDefaultAmount` -- the defaulted
      loan's exposure leaves the vault.
  (2) Symmetric cash inflow: `defaultCovered` returns from first-loss
      capital. Apply the same STAmount to both `sfAssetsTotal` and
      `sfAssetsAvailable`, preserving the gap.

Because both deltas are STAmounts of the same asset, no cross-scale
rounding step is needed and `Available > Total` cannot occur from
arithmetic. The dust-branch snap and its downstream `tecINTERNAL`
guard are unreachable under the fix and only run on the pre-amendment
path.

The pre-mutation sanity check on the fix path tightens to the correct
invariant (`sfAssetsTotal - sfAssetsAvailable >= totalDefaultAmount`);
the pre-amendment path retains its original `vaultTotalProxy <
vaultDefaultAmount` check for byte-for-byte compatibility with existing
ledgers.

`LoanRounding_test` now runs `testDustManipulation` (and the other
amendment-sensitive rounding tests) under both branches by adding
`fixCleanup3_4_0` to the `amendmentCombinations` matrix. Both branches
land the same post-default equality for the specific test setup; the
fix path reaches it by clean arithmetic rather than a snap.
2026-08-11 18:15:54 +02:00
klemenfn
a3147740f2 build: Fix GCC 14 compilation (#7981)
Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
2026-08-11 13:24:56 +00:00
luisfernandomendozav
d43e5acaa7 fix: Validate account/ident type in gateway_balances (#7655) 2026-08-11 13:23:07 +00:00
Ayaz Salikhov
c74724a719 build: Reimagine linker warnings in different scenarios (#7974) 2026-08-11 12:44:01 +00:00
Alex Kremer
0a572833ea chore: Gtest migration followups second pass (#7888) 2026-08-11 12:38:40 +00:00
Chenna Keshava B S
639943123c fix: Validate buy/sell flag in nft RPC input (#7725) 2026-08-11 00:49:02 +00:00
Bryan
909cc5bba9 fix: Prevent silent zero AMM clawbacks due to integer MPT rounding (#7704)
Co-authored-by: Bart <bthomee@users.noreply.github.com>
2026-08-10 21:37:53 +00:00
Peter Chen
6f5de9067a chore: Mark unreachable branches in Confidential Transfer with UNREACHABLE (#7903) 2026-08-10 21:37:38 +00:00
Kassaking7
60291c3ed6 fix: Allow OverrideFreeze to bypass individual/deep freeze on AMM trust lines (#6959) 2026-08-10 21:34:28 +00:00
Braedon Klock
4173f7e499 fix: Validate account_lines peer field type (#7728)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-08-10 21:30:06 +00:00
Ayaz Salikhov
9c292fbe4f build: Install conan configuration/profiles inside Nix devshell (#7997) 2026-08-10 17:49:29 +00:00
yinyiqian1
b19c3c64f2 fix: Add zero keylet check in credential (#7971) 2026-08-10 17:47:16 +00:00
Mayukha Vadari
a0e1e578a0 refactor: Remove operator!= overloads that C++20 synthesizes (#7994) 2026-08-10 17:23:02 +00:00
Mayukha Vadari
07aa97fda4 test: Use std::string::starts_with/ends_with instead of Boost (#7992) 2026-08-10 17:22:40 +00:00
Mayukha Vadari
4f8819565a fix: Assorted cleanup fixes (#7988) 2026-08-10 17:18:22 +00:00
Mayukha Vadari
6580b200db refactor: Replace boost::lexical_cast with existing alternatives (#7991) 2026-08-10 17:10:18 +00:00
Mayukha Vadari
2967f1f0cc chore: Remove unreferenced legacy documents (#7989) 2026-08-10 17:06:29 +00:00
Mayukha Vadari
71e972cbed refactor: Act on TODOs that are unblocked by C++23 (#7990) 2026-08-10 17:05:18 +00:00
Ayaz Salikhov
a24caaa6ea docs: Rearrange & simplify build/nix/environment docs (#7985) 2026-08-10 15:00:30 +00:00
Vito
db50afa34f test: Cover Vault helper early-return branches
Adds unit-test coverage for three previously-untested branches in
VaultHelpers:

- addVaultAssets propagates a non-tes return when the underlying
  accountSend fails (exercised via a sender with no trust line for the
  vault asset).
- clawbackVaultAssets propagates a non-tes return when its accountSend
  fails (exercised via a synthetic third-party recipient with no trust
  line; the production caller always uses the asset issuer, which
  cannot hit this branch).
- moveVaultAssets short-circuits and returns tesSUCCESS without
  touching accountSendMulti when every recipient's amount is zero
  (exercised via two zero-amount recipients, which still satisfies the
  recipients.size() > 1 precondition).
2026-08-10 16:34:36 +02:00
Vito
0a4dd08700 chore: Address inline review comments on Vault helpers
- Restore the doc comment on STAmount::isRounded that was lost when it
  moved out of LendingHelpers.cpp.
- Collapse LoanManage::defaultLoan's Vault-update block into a direct
  return of addVaultAssets, since there is no follow-up work after it.
- Mark removeVaultAssets's amount==0 early-return with LCOV_EXCL_LINE: it
  is a defensive short-circuit for a branch that is only reachable in a
  vanishingly rare edge case (final withdrawal from a vault whose
  sfAssetsAvailable has already been written down to zero) and is not
  reached by any current transactor-level test.
2026-08-10 16:34:29 +02:00
Vito
5d839f4811 fix: Silence -Wunused-variable on Vault clawback/withdraw asserts
Mark `assetsAvailable`/`assetsTotal` in VaultClawback::doApply and
`assetsTotalBefore` in VaultWithdraw::doApply as [[maybe_unused]]: each
is only referenced from XRPL_ASSERT, which is compiled out in Release
(NDEBUG) builds. Without the attribute clang -Werror,-Wunused-variable
would break the release CI configurations, matching the pattern already
addressed for VaultHelpers and LoanPay.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-10 15:36:07 +02:00
Ayaz Salikhov
07b9c59b89 build: Remove protobuf dependencies from Nix (#7984) 2026-08-10 13:08:15 +00:00
Vito
00889a4307 fix: Silence -Wunused-variable on LoanPay asset asserts
Mark the raw pre-rounding projections `assetsAvailableAfterRaw` and
`assetsTotalAfterRaw` in LoanPay::doApply as [[maybe_unused]]: they are
only referenced from XRPL_ASSERT_PARTS, which is compiled out in Release
(NDEBUG) builds, so clang's -Werror,-Wunused-variable was breaking the
ubuntu-clang-release-amd64 and macos-arm64-release CI jobs.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-10 14:34:08 +02:00
Sergey Kuznetsov
63d8772f69 chore: Remove corrosion from nix (#7982) 2026-08-10 11:58:49 +00:00
Vito
d6565f0e4d fix: Silence -Wunused-variable on the asset asserts
Mark the `Asset const asset` local in addVaultAssets and removeVaultAssets
as [[maybe_unused]]: it is only referenced from XRPL_ASSERT, which is
compiled out in Release (NDEBUG) builds, so clang's -Werror,
-Wunused-variable was breaking the ubuntu-clang-release-amd64 CI job.
The moveVaultAssets copy is used in real code paths and is unaffected.
2026-08-10 13:29:24 +02:00
Vito Tumas
72f75cbf43 Merge branch 'develop' into tapanito/vault-add-assets-helper 2026-08-10 12:51:59 +02:00
Vito
80ef2659e0 test: Add unit tests for the Vault balance-mutation helpers
Exercise addVaultAssets, clawbackVaultAssets, removeVaultAssets
(including FinalRemoval::Yes hard-reset and the amount > sfAssetsAvailable
failure path), and moveVaultAssets directly against a real Vault SLE and
ApplyView, built via jtx but bypassing the VaultDeposit/VaultWithdraw/
VaultClawback/LoanSet transactors. Covers zero-amount edges, negative
valueDelta, and the independent amount/valueDelta contract, in addition
to the existing transactor-level coverage in Vault_test.cpp,
LoanSet_test.cpp, etc.
2026-08-10 12:41:00 +02:00
Vito
518edd594c refactor: Route Vault/Loan transactors through the new Vault helpers
Wire VaultDeposit, VaultWithdraw, VaultClawback, LoanSet, LoanManage, and
LoanPay through addVaultAssets/removeVaultAssets/clawbackVaultAssets/
moveVaultAssets, replacing their ad hoc sfAssetsTotal/sfAssetsAvailable
proxy mutations and accountSend/accountSendMulti/doWithdraw calls:

- VaultDeposit and VaultWithdraw/VaultClawback use addVaultAssets and
  removeVaultAssets/clawbackVaultAssets respectively. VaultClawback uses
  the plain-accountSend overload rather than the doWithdraw-based one,
  since doWithdraw's self-holding-creation path would incorrectly reject
  a locked/frozen MPT issuance before checking that the recipient is the
  issuer (who always already holds their own asset).
- LoanSet's loan-principal-and-origination-fee disbursement uses
  moveVaultAssets.
- LoanManage's default write-off and LoanPay's payment both use
  addVaultAssets; addVaultAssets always applies valueDelta even when the
  transferred amount is zero, since a default written off entirely by
  the Vault (no first-loss capital cover) has a nonzero total delta but
  a zero transferred amount.
- LoanPay's post-rounding precision-loss guard now reads the Vault's
  actual post-rounding field values (after addVaultAssets/associateAsset
  have mutated and rounded them) instead of comparing raw pre-mutation
  arithmetic.
- associateAsset(*vault, ...) must run after the helper mutates the
  Vault's fields, never before: it rounds every asset-typed field on the
  Vault SLE to the asset's canonical precision, which the mutation
  itself does not do. Getting this ordering backwards is what caused a
  "value is already rounded" STNumber assertion failure during testing.

Also rename getAssetsTotalScale to VaultHelpers::getVaultScale at all
call sites.
2026-08-10 12:40:46 +02:00
Vito
3c51e3dad1 feat: Centralize Vault balance mutations in VaultHelpers
Add addVaultAssets, removeVaultAssets (two overloads: plain accountSend
and doWithdraw-based), clawbackVaultAssets, and moveVaultAssets as the
single points through which a Vault's sfAssetsTotal/sfAssetsAvailable are
mutated and funds move to/from its pseudo-account:

- addVaultAssets increases both fields and transfers in from a sender.
- removeVaultAssets/clawbackVaultAssets decrease both fields equally and
  transfer out; a FinalRemoval flag hard-resets both fields to exactly
  zero on a Vault's last withdrawal, since the discounted exchange-rate
  formula can produce values with more precision than the asset can
  canonically represent, and subtracting such a value would leave a
  non-canonical residual instead of an exact zero.
- moveVaultAssets decreases only sfAssetsAvailable, for disbursements
  (e.g. a loan's principal and origination fee) where sfAssetsTotal
  independently grows via accrued interest.

Also consolidate getAssetsTotalScale into VaultHelpers::getVaultScale,
and move isRounded from LendingHelpers into STAmount.h alongside the
other rounding utilities.
2026-08-10 12:40:10 +02:00
Gregory Tsipenyuk
94bccb3a5a fix: Fix MPT/DEX Audit/Attackathon reports (Phase 2) (#7537)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Sergey Kuznetsov <skuznetsov@ripple.com>
Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
Co-authored-by: Andrzej Budzanowski <andrzej.budzanowski@neti-soft.com>
Co-authored-by: Marek Foss <marek.foss@neti-soft.com>
Co-authored-by: Alex Kremer <akremer@ripple.com>
Co-authored-by: Vito Tumas <5780819+Tapanito@users.noreply.github.com>
Co-authored-by: Bart <bthomee@users.noreply.github.com>
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
Co-authored-by: Mayukha Vadari <mvadari@ripple.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-07 21:53:54 +00:00
Mayukha Vadari
0fb92c3194 refactor: Use SeqProxy instead of uint32 for all sequence-based keylets (#7890)
Co-authored-by: xrplf-ai-reviewer[bot] <266832837+xrplf-ai-reviewer[bot]@users.noreply.github.com>
2026-08-07 21:29:11 +00:00
Matt Van Horn
798e889ec4 fix: Deduplicate oracle entries in get_aggregate_price RPC (#6586)
Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Mayukha Vadari <mvadari@ripple.com>
Co-authored-by: Bart <bthomee@users.noreply.github.com>
2026-08-07 20:24:45 +00:00
Timur Yalymov
abf5511d07 fix: Correct sign-check wording in lending protocol messages (#7913) 2026-08-07 19:41:23 +00:00
Ayaz Salikhov
a0e78b286f chore: Bump version to 3.4.0-b0 (#7976) 2026-08-07 16:56:46 +00:00
Ayaz Salikhov
9859e5ceda Merge remote-tracking branch 'upstream/release/3.3.x' into mathbunnyru/merge-3.3.0-to-develop
* upstream/release/3.3.x: (41 commits)
  chore: Bump version to 3.3.0
  chore: Bump version to 3.3.0-rc7
  fix: Increase manifest protocol message size cap and fix manifests relay
  fix: Cap untrusted manifests per message and drop oversized ones
  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
  chore: Bump version to 3.3.0-rc6
  feat: Package validator-keys inside rippled
  chore: Bump version to 3.3.0-rc5
  fix: Switch SponsorshipSet to use a delta for sfFeeAmount
  fix: Re-revert "fix: Set request size limits and differential pricing for get-object-by-hash calls"
  chore: Bump version to 3.3.0-rc4
  fix: Revert "fix: Set request size limits and differential pricing for get-object-by-hash calls"
  chore: Bump version to 3.3.0-rc3
  fix: Reduce untrusted manifest cache cap to 100
  fix: Revert "fix: Reject oversized SHAMap nodes in gotStaleData and fetch-pack path"
  ...
2026-08-07 16:00:25 +01:00
Ayaz Salikhov
00a178fb92 chore: Bump version to 3.3.0 2026-08-06 17:34:39 +01:00
Ayaz Salikhov
cb425647a4 ci: Generate protocol_autogen only once in CI (#7918) 2026-08-06 13:25:28 +00:00
Ayaz Salikhov
5bf24c4045 ci: Use a separate benchmark filter (#7919) 2026-08-06 11:04:41 +00:00
Gregory Tsipenyuk
8d7524f03b fix: Use consistent endianness serializing MPT STIssue sequence (#7429)
Co-authored-by: Ed Hennis <ed@ripple.com>
Co-authored-by: David Fuelling <sappenin@gmail.com>
2026-08-05 17:54:44 +00:00
Ayaz Salikhov
41d6bb5f73 build: Fix build on macOS 15 and Nix environment (#7953) 2026-08-04 23:27:23 +00:00
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
Ayaz Salikhov
a75488e5ff docs: Add a fix for command not found: nix on macOS (#7951) 2026-08-04 16:17:41 +00:00
Vito Tumas
c3ee602002 test: Split Loan_test.cpp into topical suites (#7864)
Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
2026-08-04 15:43:59 +00:00
Vito Tumas
e0de716ee6 fix: Watch nix/*.nix files for direnv cache invalidation (#7948) 2026-08-04 13:49:18 +00:00
Alex Kremer
06488c1318 chore: Rename CamelCase namespaces to snake_case (#7933)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-08-04 13:46:55 +00:00
Luc des Trois Maisons
b8451ffa32 fix: Add missing value_type to JSON iterators (#7907) 2026-08-03 21:17:23 +00:00
Timur Yalymov
765babb20d fix: Add VaultInvariant check that lossUnrealized is non-negative (#7863)
Co-authored-by: Vito Tumas <5780819+Tapanito@users.noreply.github.com>
2026-08-03 21:11:33 +00:00
Braedon Klock
97f35add2e fix: Add null check for account object reads (#7717)
Co-authored-by: Mayukha Vadari <mvadari@ripple.com>
2026-08-03 21:08:42 +00:00
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
Alex Kremer
ecdd457f35 chore: Gtest migration followups first pass (#7884) 2026-07-30 23:04:38 +00:00
Ayaz Salikhov
85e73cbd32 ci: Run coverage first in CI (#7917) 2026-07-30 19:28:31 +00:00
Bart
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
21cd615407 perf: Replace node ID by depth in TMLedgerNode (#6353)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
2026-07-30 15:02:05 +00:00
Olek
3c0659d26b test: Add confidential mpt bulletproof tests (#7816) 2026-07-30 12:18:33 +00:00
Copilot
532506541f fix: Apply asfDisallowIncomingTrustline blocker to OfferCreate (#6307)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Mayukha Vadari <mvadari@gmail.com>
Co-authored-by: Mayukha Vadari <mvadari@ripple.com>
2026-07-30 12:17:32 +00:00
Vito Tumas
8a5eded4f1 feat: Implement LoanBroker cash-basis accounting (#7817) 2026-07-30 11:55:39 +00:00
Alex Kremer
6ddad54985 chore: Move lexical cast tests to gtest (#7873) 2026-07-29 22:54:46 +00:00
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
Alex Kremer
86832edc70 chore: Move semantic version tests to gtest (#7872)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-27 18:48:53 +00:00
Ayaz Salikhov
ff7fff2cf2 style: Make clang-tidy format files using clang-format rules (#7880) 2026-07-27 18:39:53 +00:00
Mayukha Vadari
2db631c915 ci: Change server_definitions upload config name (#7878) 2026-07-27 17:42:07 +00:00
Alex Kremer
6c9c7f0555 chore: Trivial gtest migrations (#7865) 2026-07-27 16:34:53 +00:00
Ayaz Salikhov
9466ecb5c2 ci: Group github-actions dependabot updates (#7876) 2026-07-27 14:32:53 +00:00
Sergey Kuznetsov
e0aa50c4be ci: Update CI image and prepare-runner action (#7874) 2026-07-27 14:18:01 +00:00
Andrzej Budzanowski
29120dfcbd test: Migrate nodestore tests from Beast to GTest (#7292)
Co-authored-by: Marek Foss <marek.foss@neti-soft.com>
Co-authored-by: Alex Kremer <akremer@ripple.com>
2026-07-27 13:00:14 +00:00
Andrzej Budzanowski
20801d98ac test: Improve the server status test to not race and randomly fail (#7304)
Co-authored-by: Alex Kremer <akremer@ripple.com>
2026-07-27 11:58:15 +00:00
dependabot[bot]
b878818e80 ci: [DEPENDABOT] bump actions/checkout from 7.0.0 to 7.0.1 (#7871)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-27 09:55:01 +00:00
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
Sergey Kuznetsov
fecfc0cf3f chore: Fix clang version in devshell (#7860)
Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
2026-07-24 17:30:20 +00:00
Ayaz Salikhov
ea0a6904f0 chore: Verify tooling version for Nix-managed environments (#7862) 2026-07-24 15:52:45 +00:00
Ayaz Salikhov
29d74142ae build: Patсh binary in local Linux nix environment (#7859)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-24 14:59:24 +00:00
Kassaking7
9afa1cf4d1 fix: Update PermissionedDEX invariant domain tracking for valid offer replacement (#7387)
Co-authored-by: Bart <bthomee@users.noreply.github.com>
2026-07-23 21:40:21 +00:00
Ed Hennis
7908aec2ec feat: Check default fields are not default when serializing (#6267)
Co-authored-by: Vito <5780819+Tapanito@users.noreply.github.com>
Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
Co-authored-by: Bart <bthomee@users.noreply.github.com>
2026-07-23 21:39:11 +00:00
Marek Foss
4c0180b3db test: Migrate csf and xrpld-consensus Beast non-JTx tests to GTest (#7046)
Co-authored-by: Alex Kremer <akremer@ripple.com>
2026-07-23 21:38:21 +00:00
Marek Foss
4acccfeda8 test: Modularize Peerfinder component and migrate Peerfinder tests from Beast to GTest and GMock (#7054)
Co-authored-by: Alex Kremer <akremer@ripple.com>
2026-07-23 21:00:06 +00:00
Ed Hennis
b89d75a2d5 test: Add an RAII class to manage the env.parseFailureExpected flag (#7669) 2026-07-23 20:57:00 +00:00
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
Ayaz Salikhov
40cdf49d15 build: Use custom libc in a devshell by default (#7852) 2026-07-23 19:05:24 +00: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
Mayukha Vadari
38c54c3f36 feat: Add fixCleanup3_4_0 amendment (no functionality yet) (#7854) 2026-07-23 18:50:59 +00:00
Sergey Kuznetsov
95e1ffea6e ci: Add llvm-tools-preview to rust toolchain (#7853) 2026-07-23 16:49:44 +00:00
Sergey Kuznetsov
74cfb3586a ci: Update CI image (#7850) 2026-07-23 11:21:49 +00:00
Ayaz Salikhov
0072ced94c ci: Update XRPLF/actions (#7849) 2026-07-23 10:22:18 +00:00
Mayukha Vadari
12ed506565 chore: Clean up grammar in PR template (#7846) 2026-07-22 18:50:10 +00:00
Ayaz Salikhov
3122de86bf build: Create versioned compiler/tooling symlinks in nix environments (#7844) 2026-07-22 17:04:02 +00:00
Sergey Kuznetsov
7edf39e622 ci: Use rust-overlay to bring Rust into nix (#7837) 2026-07-22 14:00:17 +00:00
dependabot[bot]
ba01b05f33 ci: [DEPENDABOT] bump actions/setup-python from 6.3.0 to 7.0.0 (#7830)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-21 16:04:45 +00:00
Sergey Kuznetsov
c414e1877d ci: Update pre-commit image (#7838) 2026-07-21 15:37:47 +00:00
Sergey Kuznetsov
f56b79f00d ci: Add cargo to pre-commit image (#7835) 2026-07-21 13:39:37 +00:00
Ayaz Salikhov
4918f3bb20 chore: Add doxygen in pre-commit image (#7836) 2026-07-21 13:38:26 +00:00
Mayukha Vadari
ee0a3dfad7 ci: Improve test debuggability (#7619)
Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
2026-07-21 13:14:40 +00:00
Bart
042c9660cd chore: Add CODEOWNERS for CI-related changes (#7832)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
2026-07-20 21:06:24 +00:00
Ayaz Salikhov
60b49f3fe0 ci: Use in-house image for pre-commit (#7610) 2026-07-20 19:11:09 +00:00
Ayaz Salikhov
4c869ee16c ci: Build separate pre-commit docker image (#7831) 2026-07-20 17:40:38 +00:00
Ayaz Salikhov
b2f45813e0 chore: Workaround boost compiler resolution inside Nix environment (#7826) 2026-07-20 14:04:08 +00: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
Vito Tumas
5ce0b1c2c7 refactor: Restructure LendingHelpers to improve readability (#7807) 2026-07-16 15:47:56 +00:00
Andrzej Budzanowski
701311f27e test: Add google benchmark dependency and migrate nodestore timing test as a benchmark (#7317)
Co-authored-by: Marek Foss <marek.foss@neti-soft.com>
Co-authored-by: Alex Kremer <akremer@ripple.com>
2026-07-16 15:44:43 +00:00
Mayukha Vadari
d569f7db9e fix: Prevent credentials from being created for pseudo-accounts 2026-07-16 11:42:27 -04:00
Sergey Kuznetsov
b1a670c46e ci: Add Rust to CI (#7808)
Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
2026-07-16 15:28:04 +00:00
Mayukha Vadari
a12ab0496c fix: Add missing pseudo-account checks 2026-07-16 11:18:26 -04:00
Bart
18e311e1e2 chore: Bump version to 3.3.0-rc1 (#7806)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
2026-07-16 13:54:12 +00:00
Denis Angell
69b70d7a0d fix: Refactor Batch Transaction IDs (#7736)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Mayukha Vadari <mvadari@ripple.com>
2026-07-16 13:15:59 +00:00
Mayukha Vadari
b42cde3e85 refactor: Remove redundant enable checks in ConfidentialMPT txs (#7809) 2026-07-16 09:51:19 +00:00
Peter Chen
cd38c0e800 chore: Update mpt-crypto-lib to 0.4.0-rc4 (#7813) 2026-07-15 23:47:22 +00:00
Vlad
433e5f6896 fix: Reject zero CheckID in CheckCancel and CheckCash (#7685) 2026-07-15 22:08:45 +00:00
Ayaz Salikhov
781ab723af ci: Fix workflow launch on matrix-unrelated labels (#7812) 2026-07-15 18:24:31 +00:00
Ed Hennis
a24e543af3 fix: Allocate TaggedCache::getKeys() memory outside of lock (#7567)
Co-authored-by: xrplf-ai-reviewer[bot] <266832837+xrplf-ai-reviewer[bot]@users.noreply.github.com>
2026-07-15 13:30:20 +00:00
Sophia Xie
a0fd1cce54 fix: Re-store nodes missing from both backends during online_delete rotation (#7763)
Co-authored-by: Valentin Balaschenko <13349202+vlntb@users.noreply.github.com>
2026-07-14 23:42:40 +00:00
825 changed files with 44562 additions and 25896 deletions

View File

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

View File

@@ -30,7 +30,9 @@ ignoreRegExpList:
- ABCDEFGHIJKLMNOPQRSTUVWXYZ
- ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
overrides:
- filename: "**/*_test.cpp" # all test files
- filename:
- "**/*_test.cpp" # legacy boost.test files
- "src/tests/**/*.cpp" # gtest test files
ignoreRegExpList:
- /"[^"]*"/g # double-quoted strings
- /'[^']*'/g # single-quoted strings
@@ -130,6 +132,7 @@ words:
- godexsoft
- gpgcheck
- gpgkey
- Hinnant
- hotwallet
- hwaddress
- hwrap
@@ -163,6 +166,7 @@ words:
- llection
- LOCALGOOD
- logwstream
- Lombrozo
- lseq
- lsmf
- ltype
@@ -172,7 +176,6 @@ words:
- MPTAMM
- MPTDEX
- Merkle
- Metafuncton
- misprediction
- missingok
- mptbalance
@@ -200,6 +203,7 @@ words:
- nftokens
- nftpage
- nikb
- Nikolaos
- nixfmt
- nixos
- nixpkgs
@@ -216,6 +220,7 @@ words:
- Nyffenegger
- onlatest
- ostr
- oxalica
- pargs
- partitioner
- paychan
@@ -243,6 +248,16 @@ words:
- queuable
- Raphson
- rcflags
- recognise
- recognises
- recognised
- renormalise
- renormalises
- renormalised
- renormalisation
- reserialise
- reserialises
- reserialised
- replayer
- rerandomize
- rerandomization
@@ -262,6 +277,8 @@ words:
- Rohrs
- roundings
- rustc
- rustfmt
- rustup
- sahyadri
- Satoshi
- scons
@@ -305,6 +322,7 @@ words:
- takerpays
- ters
- TMEndpointv2
- toolchain
- tparam
- trixie
- tx
@@ -337,6 +355,7 @@ words:
- unsquelch
- unsquelched
- unsquelching
- unsuffixed
- unvalidated
- unveto
- unvetoed
@@ -356,6 +375,7 @@ words:
- xchain
- ximinez
- XMACRO
- xored
- xrpkuwait
- xrpl
- xrpld

6
.envrc
View File

@@ -1 +1,7 @@
watch_file nix/*.nix
# The dev shell derivation includes all of conan/ (see nix/devshell.nix), so any
# change in there has to invalidate direnv's cached environment.
watch_dir conan
use flake

View File

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

View File

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

View File

@@ -1,10 +1,10 @@
<!--
This PR template helps you to write a good pull request description.
This PR template helps you 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 unnecessary redundant test runs. Renaming
opening the PR. This avoids 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 a relevant task or issue, please link it here.
If there is 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 PR.
For future tasks related to this 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 |
| 07 | xrpl/shamap xrpl/consensus |
## xrpld Modules (Application Implementation)
| Level / Tier | Module(s) |
| ------------ | -------------------------------- |
| 05 | xrpld/conditions xrpld/consensus |
| 06 | xrpld/core xrpld/peerfinder |
| 07 | xrpld/shamap xrpld/overlay |
| 08 | xrpld/app |
| 09 | xrpld/rpc |
| 10 | xrpld/perflog |
| Level / Tier | Module(s) |
| ------------ | --------------------------- |
| 05 | xrpld/conditions |
| 06 | xrpld/core xrpld/peerfinder |
| 07 | xrpld/shamap xrpld/overlay |
| 08 | xrpld/app |
| 09 | xrpld/rpc |
| 10 | xrpld/perflog |
## Test Modules

View File

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

View File

@@ -1,8 +1,13 @@
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
@@ -22,6 +27,9 @@ libxrpl.nodestore > xrpl.config
libxrpl.nodestore > xrpl.json
libxrpl.nodestore > xrpl.nodestore
libxrpl.nodestore > xrpl.protocol
libxrpl.peerfinder > xrpl.basics
libxrpl.peerfinder > xrpl.peerfinder
libxrpl.peerfinder > xrpl.protocol
libxrpl.protocol > xrpl.basics
libxrpl.protocol > xrpl.json
libxrpl.protocol > xrpl.protocol
@@ -57,9 +65,9 @@ test.app > test.jtx
test.app > test.unit_test
test.app > xrpl.basics
test.app > xrpl.config
test.app > xrpl.consensus
test.app > xrpl.core
test.app > xrpld.app
test.app > xrpld.consensus
test.app > xrpld.core
test.app > xrpld.overlay
test.app > xrpld.rpc
@@ -80,12 +88,9 @@ test.basics > xrpl.protocol
test.beast > xrpl.basics
test.conditions > xrpl.basics
test.conditions > xrpl.conditions
test.consensus > test.csf
test.consensus > test.jtx
test.consensus > test.unit_test
test.consensus > xrpl.basics
test.consensus > xrpld.app
test.consensus > xrpld.consensus
test.consensus > xrpl.ledger
test.consensus > xrpl.protocol
test.consensus > xrpl.shamap
@@ -100,10 +105,6 @@ test.core > xrpl.json
test.core > xrpl.protocol
test.core > xrpl.rdb
test.core > xrpl.server
test.csf > xrpl.basics
test.csf > xrpld.consensus
test.csf > xrpl.json
test.csf > xrpl.ledger
test.json > test.jtx
test.json > xrpl.json
test.jtx > test.unit_test
@@ -129,12 +130,9 @@ test.ledger > xrpl.json
test.ledger > xrpl.ledger
test.ledger > xrpl.protocol
test.nodestore > test.jtx
test.nodestore > test.unit_test
test.nodestore > xrpl.basics
test.nodestore > xrpl.config
test.nodestore > xrpld.core
test.nodestore > xrpl.nodestore
test.nodestore > xrpl.protocol
test.nodestore > xrpl.rdb
test.overlay > test.jtx
test.overlay > test.unit_test
@@ -143,19 +141,13 @@ test.overlay > xrpl.config
test.overlay > xrpld.app
test.overlay > xrpld.core
test.overlay > xrpld.overlay
test.overlay > xrpld.peerfinder
test.overlay > xrpl.json
test.overlay > xrpl.nodestore
test.overlay > xrpl.peerfinder
test.overlay > xrpl.protocol
test.overlay > xrpl.resource
test.overlay > xrpl.server
test.overlay > xrpl.shamap
test.peerfinder > test.beast
test.peerfinder > test.unit_test
test.peerfinder > xrpl.basics
test.peerfinder > xrpld.core
test.peerfinder > xrpld.peerfinder
test.peerfinder > xrpl.protocol
test.protocol > test.jtx
test.protocol > test.unit_test
test.protocol > xrpl.basics
@@ -189,11 +181,13 @@ test.unit_test > xrpl.basics
test.unit_test > xrpl.protocol
tests.libxrpl > xrpl.basics
tests.libxrpl > xrpl.config
tests.libxrpl > xrpl.consensus
tests.libxrpl > xrpl.core
tests.libxrpl > xrpl.json
tests.libxrpl > xrpl.ledger
tests.libxrpl > xrpl.net
tests.libxrpl > xrpl.nodestore
tests.libxrpl > xrpl.peerfinder
tests.libxrpl > xrpl.protocol
tests.libxrpl > xrpl.protocol_autogen
tests.libxrpl > xrpl.resource
@@ -203,6 +197,10 @@ tests.libxrpl > xrpl.tx
xrpl.conditions > xrpl.basics
xrpl.conditions > xrpl.protocol
xrpl.config > xrpl.basics
xrpl.consensus > xrpl.basics
xrpl.consensus > xrpl.json
xrpl.consensus > xrpl.ledger
xrpl.consensus > xrpl.protocol
xrpl.core > xrpl.basics
xrpl.core > xrpl.json
xrpl.core > xrpl.protocol
@@ -217,6 +215,8 @@ xrpl.nodestore > xrpl.basics
xrpl.nodestore > xrpl.config
xrpl.nodestore > xrpl.json
xrpl.nodestore > xrpl.protocol
xrpl.peerfinder > xrpl.basics
xrpl.peerfinder > xrpl.protocol
xrpl.protocol > xrpl.basics
xrpl.protocol > xrpl.json
xrpl.protocol_autogen > xrpl.json
@@ -243,23 +243,20 @@ xrpl.tx > xrpl.protocol
xrpld.app > test.unit_test
xrpld.app > xrpl.basics
xrpld.app > xrpl.config
xrpld.app > xrpl.consensus
xrpld.app > xrpl.core
xrpld.app > xrpld.consensus
xrpld.app > xrpld.core
xrpld.app > xrpl.json
xrpld.app > xrpl.ledger
xrpld.app > xrpl.net
xrpld.app > xrpl.nodestore
xrpld.app > xrpl.peerfinder
xrpld.app > xrpl.protocol
xrpld.app > xrpl.rdb
xrpld.app > xrpl.resource
xrpld.app > xrpl.server
xrpld.app > xrpl.shamap
xrpld.app > xrpl.tx
xrpld.consensus > xrpl.basics
xrpld.consensus > xrpl.json
xrpld.consensus > xrpl.ledger
xrpld.consensus > xrpl.protocol
xrpld.core > xrpl.basics
xrpld.core > xrpl.config
xrpld.core > xrpl.core
@@ -268,21 +265,22 @@ xrpld.core > xrpl.protocol
xrpld.core > xrpl.rdb
xrpld.overlay > xrpl.basics
xrpld.overlay > xrpl.config
xrpld.overlay > xrpl.consensus
xrpld.overlay > xrpl.core
xrpld.overlay > xrpld.consensus
xrpld.overlay > xrpld.core
xrpld.overlay > xrpld.peerfinder
xrpld.overlay > xrpl.json
xrpld.overlay > xrpl.ledger
xrpld.overlay > xrpl.peerfinder
xrpld.overlay > xrpl.protocol
xrpld.overlay > xrpl.resource
xrpld.overlay > xrpl.server
xrpld.overlay > xrpl.shamap
xrpld.overlay > xrpl.tx
xrpld.peerfinder > xrpl.basics
xrpld.peerfinder > xrpl.config
xrpld.peerfinder > xrpld.app
xrpld.peerfinder > xrpld.core
xrpld.peerfinder > xrpl.protocol
xrpld.peerfinder > xrpl.peerfinder
xrpld.peerfinder > xrpl.rdb
xrpld.perflog > xrpl.basics
xrpld.perflog > xrpl.config

View File

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

View File

@@ -33,6 +33,10 @@ 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
@@ -43,6 +47,7 @@ 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 = ""
@@ -81,6 +86,7 @@ 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:
@@ -125,6 +131,7 @@ class MatrixEntry:
cmake_args: str
cmake_target: str
build_only: bool
benchmark: bool
build_type: str
architecture: Architecture
sanitizers: str
@@ -136,7 +143,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
@@ -193,6 +201,7 @@ 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,
@@ -210,14 +219,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,
)
@@ -245,6 +259,7 @@ 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,13 +1,23 @@
{
"image_tag": "sha-e29b523",
"image_tag": "sha-fecfc0c",
"configs": {
"ubuntu": [
{
"compiler": ["gcc"],
"build_type": ["Debug"],
"arch": ["amd64"],
"minimal": true,
"suffix": "coverage",
"extra_cmake_args": "-DUNIT_TEST_REFERENCE_FEE=500 -Dcoverage=ON -Dcoverage_format=xml -DCODE_COVERAGE_VERBOSE=ON -DCMAKE_C_FLAGS=-O0 -DCMAKE_CXX_FLAGS=-O0"
},
{
"compiler": ["clang"],
"build_type": ["Release"],
"arch": ["amd64"],
"minimal": true
"minimal": true,
"benchmark": true
},
{
"compiler": ["gcc"],
"build_type": ["Release"],
@@ -29,14 +39,6 @@
"sanitizers": ["address", "undefinedbehavior"]
},
{
"compiler": ["gcc"],
"build_type": ["Debug"],
"arch": ["amd64"],
"minimal": true,
"suffix": "coverage",
"extra_cmake_args": "-DUNIT_TEST_REFERENCE_FEE=500 -Dcoverage=ON -Dcoverage_format=xml -DCODE_COVERAGE_VERBOSE=ON -DCMAKE_C_FLAGS=-O0 -DCMAKE_CXX_FLAGS=-O0"
},
{
"compiler": ["clang"],
"build_type": ["Debug"],
@@ -68,7 +70,8 @@
"compiler": ["gcc"],
"build_type": ["Release"],
"arch": ["amd64"],
"minimal": false
"minimal": false,
"extra_cmake_args": "-Dvalidator_keys=ON"
}
],
@@ -77,7 +80,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,20 +8,24 @@ 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:
@@ -36,7 +40,7 @@ defaults:
jobs:
build-merge:
name: Build and push nix-${{ matrix.distro.name }}
name: Build and push `nix-${{ matrix.distro.name }}` image
permissions:
contents: read
packages: write
@@ -54,7 +58,7 @@ jobs:
base_image: debian:bookworm
- name: rhel
base_image: registry.access.redhat.com/ubi9/ubi:latest
uses: XRPLF/actions/.github/workflows/build-multiarch-image.yml@ee03d31bcc4501d7599dc1b1ecd7a34af582ad1c
uses: XRPLF/actions/.github/workflows/build-multiarch-image.yml@9e7e4e80af9e684c116b38369add8eea64451f32
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 }}
name: Build and push `packaging-${{ matrix.distro.name }}` image
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@ee03d31bcc4501d7599dc1b1ecd7a34af582ad1c
uses: XRPLF/actions/.github/workflows/build-multiarch-image.yml@9e7e4e80af9e684c116b38369add8eea64451f32
with:
image_name: xrpld/packaging-${{ matrix.distro.name }}
dockerfile: package/Dockerfile

View File

@@ -0,0 +1,38 @@
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@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- 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@cba1f0891650baf1a9c88624dc2d72573be2eb81
uses: XRPLF/actions/.github/workflows/check-pr-title.yml@d7c65e49225a38f6d8010eacf017bb5a98d7476c

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

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

View File

@@ -25,18 +25,11 @@ on:
- unlabeled
concurrency:
# Use a per-ref group so a newer run (a push, or a change to a label below)
# supersedes the in-progress one for that ref. Label events we don't act on get
# their own unique group (per run id) instead, keeping them out of the shared
# group so real builds keep running. Keep this list in sync with `should-run`.
group: >-
${{ github.workflow }}-${{ github.ref }}${{
((github.event.action == 'labeled' || github.event.action == 'unlabeled')
&& github.event.label.name != 'Ready to merge'
&& github.event.label.name != 'DraftRunCI'
&& github.event.label.name != 'Full CI build')
&& format('-{0}', github.run_id) || ''
}}
# A single per-ref group with cancel-in-progress means any newer run (a push
# or a label change) supersedes the in-progress one for that ref. Keeping
# exactly one authoritative run per ref ensures a fast do-nothing run can never
# mask a real build's checks.
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
defaults:
@@ -44,26 +37,22 @@ defaults:
shell: bash
jobs:
# This job determines whether the rest of the workflow should run. It runs
# when the PR is not a draft (which should also cover merge-group) or has the
# 'DraftRunCI' or 'Full CI build' label. For label events it only runs when the
# label added or removed is one we act on ('Ready to merge', 'DraftRunCI' or
# 'Full CI build'), so unrelated label changes do not trigger a redundant run.
# This job determines whether the rest of the workflow should run at all,
# based on the current set of labels: it runs when the PR is not a draft
# (which should also cover merge-group) or has the 'DraftRunCI' or
# 'Full CI build' label. Whether a build then happens, and whether it is the
# minimal or full matrix, is decided further below and in the strategy matrix.
should-run:
if: >-
${{
((github.event.action != 'labeled' && github.event.action != 'unlabeled')
|| github.event.label.name == 'Ready to merge'
|| github.event.label.name == 'DraftRunCI'
|| github.event.label.name == 'Full CI build')
&& (!github.event.pull_request.draft
|| contains(github.event.pull_request.labels.*.name, 'DraftRunCI')
|| contains(github.event.pull_request.labels.*.name, 'Full CI build'))
!github.event.pull_request.draft
|| contains(github.event.pull_request.labels.*.name, 'DraftRunCI')
|| contains(github.event.pull_request.labels.*.name, 'Full CI build')
}}
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Determine changed files
# This step checks whether any files have changed that should
# cause the next jobs to run. We do it this way rather than
@@ -93,6 +82,7 @@ jobs:
.github/scripts/strategy-matrix/**
.github/workflows/reusable-build-test-config.yml
.github/workflows/reusable-build-test.yml
.github/workflows/reusable-check-autogen.yml
.github/workflows/reusable-clang-tidy.yml
.github/workflows/reusable-package.yml
.github/workflows/reusable-strategy-matrix.yml
@@ -101,6 +91,7 @@ jobs:
.clang-tidy
.codecov.yml
bin/check-tools.sh
bin/default-loader-path.sh
cfg/**
cmake/**
conan/**
@@ -136,6 +127,11 @@ jobs:
outputs:
go: ${{ steps.go.outputs.go == 'true' }}
check-autogen:
needs: should-run
if: ${{ needs.should-run.outputs.go == 'true' }}
uses: ./.github/workflows/reusable-check-autogen.yml
check-levelization:
needs: should-run
if: ${{ needs.should-run.outputs.go == 'true' }}
@@ -210,6 +206,7 @@ jobs:
passed:
if: failure() || cancelled()
needs:
- check-autogen
- check-levelization
- check-rename
- clang-tidy

View File

@@ -20,6 +20,7 @@ on:
- ".github/scripts/strategy-matrix/**"
- ".github/workflows/reusable-build-test-config.yml"
- ".github/workflows/reusable-build-test.yml"
- ".github/workflows/reusable-check-autogen.yml"
- ".github/workflows/reusable-clang-tidy.yml"
- ".github/workflows/reusable-package.yml"
- ".github/workflows/reusable-strategy-matrix.yml"
@@ -28,6 +29,7 @@ on:
- ".clang-tidy"
- ".codecov.yml"
- "bin/check-tools.sh"
- "bin/default-loader-path.sh"
- "cfg/**"
- "cmake/**"
- "conan/**"
@@ -66,6 +68,9 @@ defaults:
shell: bash
jobs:
check-autogen:
uses: ./.github/workflows/reusable-check-autogen.yml
clang-tidy:
uses: ./.github/workflows/reusable-clang-tidy.yml
permissions:

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@1bde119a1ab71305ba5d3716e7a82cea1c7bdede
uses: XRPLF/actions/.github/workflows/pre-commit.yml@3ba08d6ddf114092891d48491fc2e26c3ba15552
with:
runs_on: ubuntu-latest
container: '{ "image": "ghcr.io/xrplf/ci/tools-rippled-pre-commit:sha-41ec7c1" }'
container: '{ "image": "ghcr.io/xrplf/xrpld/pre-commit:sha-f56b79f" }'

View File

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

View File

@@ -3,6 +3,12 @@ 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
@@ -100,9 +106,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)
@@ -110,10 +117,10 @@ jobs:
uses: XRPLF/actions/cleanup-workspace@c7d9ce5ebb03c752a354889ecd870cadfc2b1cd4
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@64ec3cf3b152b4444638f470bbd6df7a7a30c81c
uses: XRPLF/actions/prepare-runner@c00c22ada3bd6bcda48fcb0d62fbbab49fec8a0f
with:
enable_ccache: ${{ inputs.ccache_enabled }}
@@ -170,9 +177,9 @@ jobs:
..
# Export the sanitizer options before any instrumented binary runs. The
# protocol code-gen and build steps below invoke instrumented dependency
# tools (protoc, grpc), so setting UBSAN_OPTIONS here lets the UBSan
# suppression list silence their diagnostics too, not just at test time.
# build step below invokes instrumented dependency tools (protoc, grpc),
# so setting UBSAN_OPTIONS here lets the UBSan suppression list silence
# their diagnostics too, not just at test time.
# GITHUB_WORKSPACE (not the github.workspace context) is used so the path
# resolves correctly inside the container job.
- name: Set sanitizer options
@@ -190,32 +197,6 @@ jobs:
echo "UBSAN_OPTIONS=include=${SUPP}/runtime-ubsan-options.txt:suppressions=${SUPP}/ubsan.supp" >>${GITHUB_ENV}
echo "LSAN_OPTIONS=include=${SUPP}/runtime-lsan-options.txt:suppressions=${SUPP}/lsan.supp" >>${GITHUB_ENV}
- name: Check protocol autogen files are up-to-date
working-directory: ${{ env.BUILD_DIR }}
env:
MESSAGE: |
The generated protocol wrapper classes are out of date.
This typically happens when the macro files or generator scripts
have changed but the generated files were not regenerated.
To fix this:
1. Run: cmake --build . --target setup_code_gen
2. Run: cmake --build . --target code_gen
3. Commit and push the regenerated files
run: |
set -e
cmake --build . --target setup_code_gen
cmake --build . --target code_gen
DIFF=$(git -C .. status --porcelain -- include/xrpl/protocol_autogen src/tests/libxrpl/protocol_autogen)
if [ -n "${DIFF}" ]; then
echo "::error::Generated protocol files are out of date"
git -C .. diff -- include/xrpl/protocol_autogen src/tests/libxrpl/protocol_autogen
echo "${MESSAGE}"
exit 1
fi
- name: Build the binary
working-directory: ${{ env.BUILD_DIR }}
env:
@@ -223,11 +204,13 @@ 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}"
--target "${CMAKE_TARGET}" \
2>&1 | tee "${GITHUB_WORKSPACE}/build.log"
- name: Show ccache statistics
if: ${{ inputs.ccache_enabled }}
@@ -247,6 +230,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
@@ -264,7 +263,7 @@ jobs:
./xrpld --definitions | python3 -m json.tool >server_definitions.json
- name: Upload server definitions
if: ${{ github.event.repository.visibility == 'public' && inputs.config_name == 'debian-gcc-release-amd64' }}
if: ${{ github.event.repository.visibility == 'public' && inputs.config_name == 'ubuntu-gcc-debug-amd64-coverage' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: server-definitions
@@ -322,27 +321,49 @@ jobs:
PRELOAD=""
fi
LD_PRELOAD="$PRELOAD" ./xrpld --unittest --unittest-jobs "${BUILD_NPROC}" 2>&1 | tee unittest.log
LD_PRELOAD="$PRELOAD" ./xrpld --unittest --unittest-jobs "${BUILD_NPROC}" 2>&1 | tee "${GITHUB_WORKSPACE}/unittest.log"
- 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 }}
# 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 }}
run: |
if [ ! -d "${WORKING_DIR}" ]; then
echo "Working directory '${WORKING_DIR}' does not exist."
exit 0
fi
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}"
cd "${WORKING_DIR}"
- name: Show build/test failure summary
if: ${{ failure() }}
run: |
cd "${GITHUB_WORKSPACE}"
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."
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
fi
- name: Debug failure (Linux)
if: ${{ failure() && runner.os == 'Linux' && !inputs.build_only }}
@@ -366,7 +387,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,6 +40,7 @@ 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

@@ -0,0 +1,76 @@
# This workflow checks that the generated protocol wrapper classes are
# up-to-date with the macro files and generator scripts they are produced from,
# see more info in include/xrpl/protocol_autogen/README.md.
name: Check autogen
# This workflow can only be triggered by other workflows.
on: workflow_call
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-autogen
cancel-in-progress: true
defaults:
run:
shell: bash
env:
BUILD_DIR: build/codegen
jobs:
autogen:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.13"
# Code generation is pure Python, so the standalone project below offers
# the same targets as the main build without needing its dependencies or
# a compiler, which keeps this job down to a few seconds.
- name: Configure CMake
run: cmake -S cmake/codegen -B "${BUILD_DIR}"
- name: Install code generation dependencies
run: cmake --build "${BUILD_DIR}" --target setup_code_gen
- name: Generate code
run: cmake --build "${BUILD_DIR}" --target code_gen
- name: Check for differences
env:
MESSAGE: |
The generated protocol wrapper classes are out of date.
This typically happens when the macro files or generator scripts
have changed but the generated files were not regenerated.
Run the following from the repository root, then commit and push
the regenerated files. This needs neither the dependencies nor a
compiler. See include/xrpl/protocol_autogen/README.md for more info.
cmake -S cmake/codegen -B build/codegen
cmake --build build/codegen --target setup_code_gen
cmake --build build/codegen --target code_gen
In an already configured build directory, the 'setup_code_gen' and
'code_gen' targets do the same thing.
run: |
# Record untracked files in the index without staging their contents,
# so that classes generated for a newly added transaction or ledger
# entry type show up in the diff below rather than silently as an
# empty one.
git add --intent-to-add .
DIFF=$(git status --porcelain)
if [ -n "${DIFF}" ]; then
# Print the differences to give the contributor a hint about what to
# expect when running code generation on their own machine.
git diff
echo "${MESSAGE}"
exit 1
fi

View File

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

View File

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

View File

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

View File

@@ -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@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.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@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- 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@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.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-e29b523
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-fecfc0c
env:
REMOTE_NAME: ${{ inputs.remote_name }}
CONAN_LOGIN_USERNAME_XRPLF: ${{ secrets.remote_username }}
CONAN_PASSWORD_XRPLF: ${{ secrets.remote_password }}
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Generate build version number
id: version

View File

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

3
.gitignore vendored
View File

@@ -81,6 +81,9 @@ 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: dd18dad857d6133e90bbe478f4f2f22ec0030269 # frozen: v22.1.5
rev: f4d7745e17a28aad7eed2f4874ca8d1568c11c4c # frozen: v22.1.8
hooks:
- id: clang-format
args: [--style=file]
@@ -68,7 +68,7 @@ repos:
- id: gersemi
- repo: https://github.com/rbubley/mirrors-prettier
rev: 39e2973981e6d2f9b6c543b0086a2d2393abdc89 # frozen: v3.9.4
rev: 9337a74165b178ae2c766f60bee7252a0f06f3e8 # frozen: v3.9.5
hooks:
- id: prettier
args: [--end-of-line=auto]

View File

@@ -42,6 +42,7 @@ This section contains changes targeting a future version.
### Bugfixes
- `get_aggregate_price`: Duplicate entries in the `oracles` request array are now ignored. [#6586](https://github.com/XRPLF/rippled/pull/6586)
- Peer Crawler: The `port` field in `overlay.active[]` now consistently returns an integer instead of a string for outbound peers. [#6318](https://github.com/XRPLF/rippled/pull/6318)
- `ping`: The `ip` field is no longer returned as an empty string for proxied connections without a forwarded-for header. It is now omitted, consistent with the behavior for identified connections. [#6730](https://github.com/XRPLF/rippled/pull/6730)
- gRPC `GetLedgerDiff`: Fixed error message that incorrectly said "base ledger not validated" when the desired ledger was not validated. [#6730](https://github.com/XRPLF/rippled/pull/6730)
@@ -53,6 +54,8 @@ This section contains changes targeting a future version.
- `submit`: The `fail_hard` field now returns an error if the value is not a boolean. [#6529](https://github.com/XRPLF/rippled/pull/6529)
- `subscribe`: The `taker` field in the `books` array now returns `actMalformed` instead of `badIssuer` if the value is not a valid account. [#6529](https://github.com/XRPLF/rippled/pull/6529)
- Fixed a bug in `Forwarded` HTTP header parsing where the extracted IP address could be incorrect when no comma or semicolon delimiter follows the address. This could cause the server to misidentify a client's IP address when operating behind a reverse proxy. [#6529](https://github.com/XRPLF/rippled/pull/6529)
- `gateway_balances`: The `account` and `ident` fields now return an `invalidParams` error if the value is not a string, instead of an `internal` error. [#7655](https://github.com/XRPLF/rippled/pull/7655)
- `account_lines`: The `peer` field now returns an error if the value is not a string. [#7728](https://github.com/XRPLF/rippled/pull/7728)
## XRP Ledger server version 3.1.0

100
BUILD.md
View File

@@ -4,34 +4,14 @@
## Minimum Requirements
See [System Requirements](https://xrpl.org/system-requirements.html).
For the hardware needed to run a node, see
[System Requirements](https://xrpl.org/system-requirements.html).
Building xrpld generally requires Git, Python, Conan, CMake, and a C++
compiler.
- [Python](https://www.python.org/downloads/)
- [Conan](https://conan.io/downloads.html)
- [CMake](https://cmake.org/download/)
You can verify that the required tools are installed and runnable with:
```bash
./bin/check-tools.sh
```
`xrpld` is written in the C++23 dialect. The [tested compiler versions][cpp23-support] are:
| Compiler | Version |
| ----------- | --------------- |
| GCC | 15.2 |
| Clang | 22 |
| Apple Clang | 21 |
| MSVC | 19.44[^windows] |
For the software needed to build xrpld, see the
[environment setup guide](./docs/build/environment.md).
## Operating Systems
Please see the [environment setup guide](./docs/build/environment.md) for detailed instructions for all platforms.
### Linux
The Ubuntu Linux distribution has received the highest level of quality
@@ -42,12 +22,13 @@ 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
Windows is used by some engineers for development only.
[^windows]: Windows is not recommended for production use.
Windows is used by some engineers for development only, and is not recommended
for production use.
## Steps
@@ -72,37 +53,25 @@ releases](https://github.com/XRPLF/rippled/releases).
### Set Up Conan
After you have a [C++ development environment](./docs/build/environment.md) ready with Git, Python,
Conan, CMake, and a C++ compiler, you may need to set up your Conan profile.
These instructions assume a basic familiarity with Conan and CMake. If you are
unfamiliar with Conan, then please read [this crash course](./docs/build/conan.md) or the official
[Getting Started][conan-getting-started] walkthrough.
#### Profiles
We recommend that you install our Conan profiles:
Once your [development environment](./docs/build/environment.md) is ready, set
Conan up for this repository:
```bash
conan config install conan/profiles/ -tf $(conan config home)/profiles/
./conan/init.sh
```
You can check your Conan profile by running:
That installs our [`global.conf`](./conan/global.conf), our Conan
[profiles](./conan/profiles), and the `xrplf` remote that hosts some of our
dependencies. It honours `CONAN_HOME` and never deletes an existing Conan home,
so it is safe to re-run — it only overwrites the files it manages.
```bash
conan profile show
```
> [!TIP]
> In the [Nix development shell](./docs/build/nix.md#conan-configuration) this is
> already done for you: the script runs on entry.
If the default profile is not suitable for your environment, you can create a custom profile and pass it to Conan.
More information on customizing Conan can be found in the [Advanced Conan configuration](./docs/build/advanced_conan.md).
#### Add xrplf remote
Run the following command to add the `xrplf` remote, which hosts some of our dependencies:
```bash
conan remote add --index 0 --force xrplf https://conan.xrplf.org/repository/conan/
```
You can inspect the resulting profile with `conan profile show`. If it is not
suitable for your environment, create a custom profile and pass it to Conan — see
[Advanced Conan configuration](./docs/build/advanced_conan.md).
### Set Up Ccache
@@ -245,7 +214,17 @@ cmake --build . --target setup_code_gen # create venv and install dependencies
cmake --build . --target code_gen # regenerate code
```
The regenerated files should be committed alongside your changes.
The same targets are also available as a standalone project, which does not
need the dependencies to be configured first:
```
cmake -S cmake/codegen -B build/codegen
cmake --build build/codegen --target setup_code_gen
cmake --build build/codegen --target code_gen
```
The regenerated files should be committed alongside your changes. CI verifies
that they are up-to-date.
## Coverage report
@@ -257,10 +236,14 @@ which is only enabled when the `coverage` option is set, e.g. with
Prerequisites for the coverage report:
- [gcovr tool][gcovr] (can be installed e.g. with [pip][python-pip])
- `gcov` for GCC (installed with the compiler by default) or
- `llvm-cov` for Clang (installed with the compiler by default)
- `gcov` for GCC or `llvm-cov` for Clang, usually installed with the compiler
- `Debug` build type
> [!NOTE]
> Clang coverage is not available in the [Nix development shell](./docs/build/nix.md#building-xrpld-in-the-nix-shell):
> its `clang` shells do not ship `llvm-cov`. Use a `gcc` shell instead (`.#gcc`,
> or `.#gcc-plain` on Linux), which provides a `gcov` matching its compiler.
A coverage report is created when the following steps are completed, in order:
1. `xrpld` binary built with instrumentation data, enabled by the `coverage`
@@ -377,10 +360,14 @@ After any updates or changes to dependencies, you may need to do the following:
4. [Regenerate lockfile](./docs/build/advanced_conan.md#conan-lockfile).
5. Re-run [conan install](#build-and-test).
If you are using the Nix development shell, whether prebuilt Conan binaries apply
depends on your platform — see
[Prebuilt packages](./docs/build/nix.md#prebuilt-packages).
#### ERROR: Package not resolved
If you're seeing an error like `ERROR: Package 'snappy/1.1.10' not resolved: Unable to find 'snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1756234314.246' in remotes.`,
please [add `xrplf` remote](#add-xrplf-remote) or re-run `conan export` for [patched recipes](./docs/build/advanced_conan.md#patched-recipes).
please [set Conan up](#set-up-conan) so the `xrplf` remote is configured, or re-run `conan export` for [patched recipes](./docs/build/advanced_conan.md#patched-recipes).
### `protobuf/port_def.inc` file not found
@@ -400,7 +387,6 @@ For example, if you want to build Debug:
1. For conan install, pass `--settings build_type=Debug`
2. For cmake, pass `-DCMAKE_BUILD_TYPE=Debug`
[cpp23-support]: https://en.cppreference.com/w/cpp/compiler_support/23
[conan-getting-started]: https://docs.conan.io/en/latest/getting_started.html
[unity-build]: https://en.wikipedia.org/wiki/Unity_build
[gcovr]: https://gcovr.com/en/stable/getting-started.html

View File

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

4
CODEOWNERS Normal file
View File

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

View File

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

View File

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

55
bin/pre-commit/Dockerfile Normal file
View File

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

View File

@@ -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
#

View File

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

View File

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

@@ -0,0 +1,38 @@
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,9 +171,8 @@ else()
# Clang wrapper supplies those paths itself (via -nostdinc++), so at compile time the
# flag is unused -> Clang errors under our -Werror. At link time the flag IS consumed
# (it selects the C++ runtime), so we move it there instead of dropping it entirely.
get_filename_component(_cxx_real "${CMAKE_CXX_COMPILER}" REALPATH)
if(
_cxx_real MATCHES "^/nix/store/"
is_nix_compiler
AND is_linux
AND is_clang
AND CMAKE_CXX_FLAGS MATCHES "stdlib=libstdc"
@@ -267,10 +266,50 @@ elseif(use_lld)
)
if("${LD_VERSION}" MATCHES "LLD")
target_link_libraries(common INTERFACE -fuse-ld=lld)
# remembered for the linker flag probe below
set(fuse_ld_flag "-fuse-ld=lld")
endif()
unset(LD_VERSION)
endif()
# Linker warnings are errors where we control the toolchain and the dependencies: CI and the Nix dev shell.
# On non-Nix macOS we suppress the deployment target warning: an old Conan profile may not pin os.version.
# Only the new Apple linker understands the flag, so probe the actual linker (lld may be selected above).
if(is_macos OR is_linux)
if(is_ci OR is_nix_compiler)
if(is_macos)
set(fatal_warnings_flag "-Wl,-fatal_warnings")
else()
set(fatal_warnings_flag "-Wl,--fatal-warnings")
endif()
message(
STATUS
"Treating all linker warnings as errors (${fatal_warnings_flag})"
)
target_link_options(common INTERFACE "${fatal_warnings_flag}")
unset(fatal_warnings_flag)
elseif(is_macos)
set(silence_flag "-Wl,-deployment_target_mismatches,suppress")
set(probe_flags ${fuse_ld_flag} "${silence_flag}")
include(CheckLinkerFlag)
check_linker_flag(
CXX
"${probe_flags}"
have_deployment_target_mismatches
)
if(have_deployment_target_mismatches)
message(
STATUS
"Silencing macOS deployment target mismatch warnings (${silence_flag})"
)
target_link_options(common INTERFACE "${silence_flag}")
endif()
unset(probe_flags)
unset(silence_flag)
endif()
endif()
unset(fuse_ld_flag)
if(assert)
foreach(var_ CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELEASE)
string(REGEX REPLACE "[-/]DNDEBUG" "" ${var_} "${${var_}}")

View File

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

View File

@@ -44,6 +44,7 @@ setup_target_for_coverage_gcovr(
EXCLUDE
"src/test"
"src/tests"
"src/benchmarks"
"include/xrpl/beast/test"
"include/xrpl/beast/unit_test"
"${CMAKE_BINARY_DIR}/pb-xrpl.libpb"

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

@@ -2,21 +2,22 @@
Protocol Autogen - Code generation for protocol wrapper classes
#]===================================================================]
# The repository root, derived from the location of this file rather than from
# the including project, so that the targets below can also be offered on their
# own by cmake/codegen/CMakeLists.txt.
get_filename_component(XRPL_ROOT "${CMAKE_CURRENT_LIST_DIR}/.." ABSOLUTE)
set(CODEGEN_VENV_DIR
"${CMAKE_CURRENT_SOURCE_DIR}/.venv"
"${XRPL_ROOT}/.venv"
CACHE PATH
"Path to a Python virtual environment for code generation. A venv will be created here by setup_code_gen and used to run generation scripts."
)
# Directory paths
set(MACRO_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include/xrpl/protocol/detail")
set(AUTOGEN_HEADER_DIR
"${CMAKE_CURRENT_SOURCE_DIR}/include/xrpl/protocol_autogen"
)
set(AUTOGEN_TEST_DIR
"${CMAKE_CURRENT_SOURCE_DIR}/src/tests/libxrpl/protocol_autogen"
)
set(SCRIPTS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/cmake/scripts/codegen")
set(MACRO_DIR "${XRPL_ROOT}/include/xrpl/protocol/detail")
set(AUTOGEN_HEADER_DIR "${XRPL_ROOT}/include/xrpl/protocol_autogen")
set(AUTOGEN_TEST_DIR "${XRPL_ROOT}/src/tests/libxrpl/protocol_autogen")
set(SCRIPTS_DIR "${XRPL_ROOT}/cmake/scripts/codegen")
# Input macro files
set(TRANSACTIONS_MACRO "${MACRO_DIR}/transactions.macro")
@@ -114,14 +115,14 @@ if(CODEGEN_VENV_DIR)
setup_code_gen
COMMAND ${Python3_EXECUTABLE} -m venv "${CODEGEN_VENV_DIR}"
COMMAND ${CODEGEN_PYTHON} -m pip install -r "${REQUIREMENTS_FILE}"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
WORKING_DIRECTORY "${XRPL_ROOT}"
COMMENT "Creating venv and installing code generation dependencies..."
)
else()
add_custom_target(
setup_code_gen
COMMAND ${Python3_EXECUTABLE} -m pip install -r "${REQUIREMENTS_FILE}"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
WORKING_DIRECTORY "${XRPL_ROOT}"
COMMENT "Installing code generation dependencies..."
)
endif()
@@ -139,8 +140,8 @@ add_custom_target(
-DSFIELDS_MACRO=${SFIELDS_MACRO}
-DAUTOGEN_HEADER_DIR=${AUTOGEN_HEADER_DIR}
-DAUTOGEN_TEST_DIR=${AUTOGEN_TEST_DIR} -P
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/XrplProtocolAutogenRun.cmake"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
"${CMAKE_CURRENT_LIST_DIR}/XrplProtocolAutogenRun.cmake"
WORKING_DIRECTORY "${XRPL_ROOT}"
COMMENT "Running protocol code generation..."
SOURCES ${ALL_INPUT_FILES}
)

View File

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

View File

@@ -30,6 +30,8 @@ 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

@@ -0,0 +1,21 @@
#[===================================================================[
Protocol Autogen - Standalone project
Exposes the 'setup_code_gen' and 'code_gen' targets on their own, without
configuring the rest of xrpl. Code generation is pure Python, so this needs
neither the dependencies nor a compiler, which makes it usable in CI and by
contributors who only want to regenerate the protocol wrapper classes:
cmake -S cmake/codegen -B build/codegen
cmake --build build/codegen --target setup_code_gen
cmake --build build/codegen --target code_gen
The targets are identical to the ones offered by the top-level build, since
both come from cmake/XrplProtocolAutogen.cmake.
#]===================================================================]
cmake_minimum_required(VERSION 3.16)
project(xrpl_codegen LANGUAGES NONE)
include("${CMAKE_CURRENT_LIST_DIR}/../XrplProtocolAutogen.cmake")

View File

@@ -2,6 +2,9 @@
#pragma once
#include <xrpl/protocol/STLedgerEntry.h>
% if any(field.get('stiSuffix') == 'NUMBER' for field in fields):
#include <xrpl/protocol/STNumber.h> // IWYU pragma: keep
% endif
#include <xrpl/protocol/STParsedJSON.h>
#include <xrpl/protocol/jss.h>
#include <xrpl/protocol_autogen/LedgerEntryBase.h>

View File

@@ -10,22 +10,24 @@
"rocksdb/10.5.1#4a197eca381a3e5ae8adf8cffa5aacd0%1782392413.075713",
"re2/20251105#8579cfd0bda4daf0683f9e3898f964b4%1782392402.431897",
"protobuf/6.33.5#ff253ead763bd8d9904a52979cd21e81%1782392410.233933",
"openssl/3.6.3#1163d4ddc603907084d08a6a0c6e580f%1782307150.583886",
"openssl/3.6.3#f806de8933e3bf6f01016c6a888cee2e%1783945160.863288",
"nudb/2.0.9#11149c73f8f2baff9a0198fe25971fc7%1782392402.297166",
"mpt-crypto/0.4.0-rc2#a580f2f9ad0e795de696aa62d54fb9af%1782425834.488828",
"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",
"libarchive/3.8.7#c446109bd1f1d8ba7936c94189bc50e6%1782392403.066892",
"jemalloc/5.3.1#1fc58d55316041f10fbc1e8a2eae632a%1776700028.228",
"gtest/1.17.0#5224b3b3ff3b4ce1133cbdd27d53ee7d%1782392402.791979",
"grpc/1.81.1#5217e6ef0544c42b46f4af35d5e7f649%1782307148.845616",
"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",
"abseil/20250127.0#bb0baf1f362bc4a725a24eddd419b8f7%1782307147.395833"
"benchmark/1.9.5#b885dc73ad67b40a55d45684d1c88ad1%1782736613.864841",
"abseil/20250127.0#9ef01c1451a8340f9022e46238c0fbb6%1783945159.651047"
],
"build_requires": [
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1782392402.122708",
@@ -33,12 +35,12 @@
"protobuf/6.33.5#ff253ead763bd8d9904a52979cd21e81%1782392410.233933",
"nasm/2.16.01#31e26f2ee3c4346ecd347911bd126904%1782395690.33162",
"msys2/cci.latest#d22fe7b2808f5fd34d0a7923ace9c54f%1770657326.649",
"m4/1.4.19#34c4bbc3eeebe98ca6edf2f52d602e7d%1777282960.259",
"m4/1.4.19#1727f439cf74e83826ec96d0b4904eee%1784541921.659",
"cmake/4.3.3#840cf00ea09777e05c2050a50a82c722%1782392418.696091",
"b2/5.4.2#ffd6084a119587e70f11cd45d1a386e2%1782392402.624226",
"automake/1.16.5#b91b7c384c3deaa9d535be02da14d04f%1755524470.56",
"autoconf/2.71#51077f068e61700d65bb05541ea1e4b0%1731054366.86",
"abseil/20250127.0#bb0baf1f362bc4a725a24eddd419b8f7%1782307147.395833"
"abseil/20250127.0#9ef01c1451a8340f9022e46238c0fbb6%1783945159.651047"
],
"python_requires": [],
"overrides": {

21
conan/init.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/usr/bin/env bash
# Install our Conan configuration, profiles and the xrplf remote into CONAN_HOME.
# Safe to re-run; never deletes the Conan home.
set -euo pipefail
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
CONAN_DIR="$(conan config home)"
echo "Installing Conan configuration into ${CONAN_DIR}"
conan config install "${SCRIPT_DIR}/global.conf"
conan config install "${SCRIPT_DIR}/profiles" -tf "${CONAN_DIR}/profiles"
# This script manages these files, so make them read-only - Conan does not
# preserve the source mode. Only the files: the directories must stay writable
# for `conan config install` to replace them.
chmod a-w "${CONAN_DIR}/global.conf"
find "${CONAN_DIR}/profiles" -type f -exec chmod a-w {} +
echo "Adding the xrplf Conan remote"
# --index 0: our patched recipes must win over Conan Center.
conan remote add --index 0 --force xrplf https://conan.xrplf.org/repository/conan/

View File

@@ -1,9 +1,13 @@
{% set os = detect_api.detect_os() %}
{% set arch = detect_api.detect_arch() %}
{% set compiler, version, compiler_exe = detect_api.detect_default_compiler() %}
{% set compiler_version = version %}
{% if os == "Linux" %}
{% set compiler_version = detect_api.default_compiler_version(compiler, version) %}
{% 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]
@@ -18,10 +22,39 @@ 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,6 +15,7 @@ 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],
@@ -28,6 +29,7 @@ class Xrpl(ConanFile):
requires = [
"ed25519/2015.03",
"fast_float/8.2.10",
"grpc/1.81.1",
"libarchive/3.8.7",
"nudb/2.0.9",
@@ -46,6 +48,7 @@ class Xrpl(ConanFile):
default_options = {
"assertions": False,
"benchmark": True,
"coverage": False,
"fPIC": True,
"jemalloc": False,
@@ -129,12 +132,14 @@ 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-rc2", 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")
@@ -162,6 +167,7 @@ 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
@@ -206,6 +212,7 @@ class Xrpl(ConanFile):
"boost::thread",
"date::date",
"ed25519::ed25519",
"fast_float::fast_float",
"grpc::grpc++",
"libarchive::libarchive",
"lz4::lz4",

View File

@@ -6,22 +6,52 @@ This document explains how to set one up.
## Tested compiler versions
`xrpld` is built in the **C++23** dialect by default.
Make sure your toolchain is recent enough — the compiler versions currently tested in CI are:
`xrpld` is built in the **C++23** dialect by default, so your toolchain has to
support it — see [compiler support for C++23][cpp23-support].
The versions currently tested in CI are:
| Compiler | Version |
| ----------- | ------- |
| GCC | 15.2 |
| Clang | 22 |
| Apple Clang | 17 |
| MSVC | 19.44 |
| Compiler | Version |
| ----------- | ------------------ |
| GCC | 15.2 |
| Clang | 22 |
| Apple Clang | 21 |
| MSVC | Visual Studio 2026 |
LLVM tools (`clang-tidy` and `clang-format`) are also pinned to version 22.
### Older compilers
Older compilers may fail to build the latest `develop` code: the codebase now
relies on C++23 features and has been adjusted for `clang-tidy`.
If the latest code doesn't build for you, update your build toolchain first.
If updating isn't an option for you, we do accept pull requests that fix builds
on older compilers, as long as the change is small and doesn't make the code
harder to read. What we can't promise is that older compilers will keep working:
only the versions in the table above are tested in CI, and we won't hold back
the use of C++23 features or add invasive workarounds to keep an untested
compiler building. Treat support for anything outside the table as best-effort.
## Required tools
Besides a compiler, building `xrpld` requires:
| Tool | Minimum version |
| ------------------------------------------- | --------------- |
| [Git](https://git-scm.com/downloads) | any recent |
| [Python](https://www.python.org/downloads/) | 3.11 |
| [Conan](https://conan.io/downloads.html) | 2.17 |
| [CMake](https://cmake.org/download/) | 3.16 |
On Linux and macOS, the [Nix development shell](./nix.md) provides all of them
(see below). On Windows they have to be installed manually.
Once they are in place, verify that everything is installed and runnable with:
```bash
./bin/check-tools.sh
```
## Linux and macOS
The **recommended way** to get a development environment on Linux and macOS is
@@ -39,20 +69,15 @@ Clang. If you instead opt to use your system-wide Apple Clang (via
below).
See [Using the Nix development shell](./nix.md) for installation and usage
details, including how to select a different compiler.
> [!NOTE]
> Using Nix is not mandatory. Any custom environment (Homebrew packages or
> anything else) will continue to work, but then it is up to you to keep it in
> sync with the environment used in CI. Nix unifies the development environment
> for everyone and synchronizes updates, which is why we recommend it.
details, including how to select a different compiler and why we recommend Nix
over a hand-maintained environment.
### macOS: managing the Apple Clang version
If you use your system-wide Apple Clang on macOS (via `nix develop .#apple-clang`),
the compiler version is whatever your installed Xcode (or Command Line Tools)
provides. The following command should return a version greater than or equal to
the [minimum required](#tested-compiler-versions):
the [tested one](#tested-compiler-versions):
```bash
clang --version
@@ -89,23 +114,23 @@ building xrpld. You may want to install and pin a specific version of Xcode:
Nix is not available on Windows, so the required tools have to be installed
manually:
- [Visual Studio 2022](https://visualstudio.microsoft.com/) with the
- [Visual Studio 2026](https://visualstudio.microsoft.com/) with the
**"Desktop development with C++"** workload — this provides MSVC and the
"x64 Native Tools Command Prompt".
"x64 Native Tools Command Prompt". CI configures CMake with the
`Visual Studio 18 2026` generator.
- [Git for Windows](https://git-scm.com/download/win)
- [Python 3.11](https://www.python.org/downloads/), or higher
- [Conan 2.17](https://conan.io/downloads.html), or higher
- [CMake 3.22](https://cmake.org/download/), or higher
> [!NOTE]
> Windows is used for development only and is not recommended for production.
- Python, Conan, and CMake, at the versions listed in
[Required tools](#required-tools).
## Clang-tidy
`clang-tidy` is required to run static analysis checks locally (see
[CONTRIBUTING.md](../../CONTRIBUTING.md)). It is not required to build the
project. This project currently uses `clang-tidy` version 22.
project. The version this project uses is listed in
[Tested compiler versions](#tested-compiler-versions).
On Linux and macOS, the [Nix development shell](./nix.md) provides `clang-tidy`
22 out of the box — run it via `run-clang-tidy`. No separate installation is
needed.
On Linux and macOS, the [Nix development shell](./nix.md) provides that exact
version out of the box — run it via `run-clang-tidy`. No separate installation
is needed.
[cpp23-support]: https://en.cppreference.com/w/cpp/compiler_support/23

70
docs/build/nix.md vendored
View File

@@ -38,8 +38,10 @@ The first time you run this command, it will take a few minutes to download and
### Platform notes
- **Linux**: `nix develop` gives you a shell with all the tooling necessary to
develop xrpld and with GCC 15.2 (also provided by Nix). There are no caveats.
- **Linux**: `nix develop` gives you a shell with all the tooling necessary to develop xrpld
and with the same GCC/glibc toolchain that Nix builds for CI.
See [Choosing a different compiler](#choosing-a-different-compiler)
for the custom-vs-plain toolchain trade-off.
- **macOS**: `nix develop` gives you a full environment too, with Clang (and
every other tool, including Conan) provided by Nix. To use your system-wide
Apple Clang instead, enter `nix develop .#apple-clang`. Conan has no binary in
@@ -63,8 +65,16 @@ The first time you run this command, it will take a few minutes to download and
### Choosing a different compiler
A compiler can be chosen by providing its name with the `.#` prefix, e.g. `nix develop .#clang`.
The `.#gcc` and `.#clang` shells provide the same GCC and Clang versions used in CI
(pinned in [`nix/packages.nix`](../../nix/packages.nix)).
On Linux, `.#gcc` and `.#clang` provide the exact toolchain CI uses:
the compiler (pinned in [`nix/packages.nix`](../../nix/packages.nix))
rebuilt against the pinned custom glibc (see [`nix/compilers.nix`](../../nix/compilers.nix)).
Building that toolchain the first time is slow unless it is fetched from a Nix binary cache.
If you don't need the custom glibc, the Linux-only `.#gcc-plain` and `.#clang-plain`
give you the stock nixpkgs compilers of the same versions.
On macOS there is no custom glibc, so `.#gcc` and `.#clang` are already the plain nixpkgs toolchain,
and the `-plain` variants do not exist.
Use `nix flake show` to see all the available development shells.
Use `nix develop .#no-compiler` to use the compiler from your system.
@@ -72,14 +82,18 @@ Use `nix develop .#no-compiler` to use the compiler from your system.
### Example Usage
```bash
# Use GCC (same version as CI)
# Use GCC same toolchain as CI (custom glibc on Linux)
nix develop .#gcc
# Use Clang (same version as CI)
# Use Clang same toolchain as CI (custom glibc on Linux)
nix develop .#clang
# Use default for your platform
nix develop
# Stock nixpkgs GCC/Clang, Linux only — skips the custom-glibc build, but does not match CI
nix develop .#gcc-plain
nix develop .#clang-plain
```
### Using a different shell
@@ -106,10 +120,36 @@ nix develop -c "$SHELL"
>
> If it doesn't, either adjust your shell configuration so it doesn't override `$PATH`, or use [direnv](#automatic-activation-with-direnv) (below), which loads the environment _after_ your shell config and so takes precedence regardless of the shell you use.
## Building xrpld with Nix
## Building xrpld in the Nix 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.
## Conan configuration
The shell runs [`conan/init.sh`](../../conan/init.sh) on entry, so
[Set Up Conan](../../BUILD.md#set-up-conan) is already done for you. It installs
into the shell's own Conan home: `CONAN_HOME=~/.conan2-nix`.
### Prebuilt packages
On **Linux**, the binaries on the `xrplf` remote are built in this same Nix
environment — CI runs in Docker images that bundle the dev shell's toolchain (see
[`nix/docker`](../../nix/docker)) — so `.#gcc` and `.#clang` can reuse them. The
`-plain` shells do not match that toolchain's glibc, so binaries from the remote
are not a reliable match there.
On **macOS**, CI builds with Apple Clang, so the remote holds nothing for the Nix
`clang` toolchain and dependencies are compiled locally. We do not publish
Nix-built macOS binaries because a Conan package ID records the compiler version
but not the nixpkgs revision.
To compile everything from source, add `--build '*'` to the `conan install`
command.
## 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.
@@ -124,18 +164,18 @@ The repository already ships an `.envrc` at its root that activates the Nix flak
> [!NOTE]
> direnv only caches the `.direnv` directory (already listed in `.gitignore`); no other repository files are affected.
## Conan and Prebuilt Packages
Please note that there is no guarantee that binaries from conan cache will work when using nix. If you encounter any errors, please use `--build '*'` to force conan to compile everything from source:
```bash
conan install .. --output-folder . --build '*' --settings build_type=Release
```
## Updating `flake.lock` file
To update `flake.lock` to the latest revision use `nix flake update` command.
## Tooling snapshots
The tool versions in each Nix environment are recorded in
[`nix/check-tools/`](../../nix/check-tools) and verified by CI. If you change the
environment (bump the CI image tag, update `flake.lock`, or edit the tool list in
`bin/check-tools.sh`), CI fails until you regenerate and commit the affected
snapshot — see [`nix/check-tools/README.md`](../../nix/check-tools/README.md).
## Troubleshooting
See [Troubleshooting Nix problems](./nix_troubleshooting.md) for common issues,

View File

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

View File

@@ -1,24 +0,0 @@
/*!
\page somestatechart Example state diagram
\startuml SomeState "my state diagram"
scale 600 width
[*] -> State1
State1 --> State2 : Succeeded
State1 --> [*] : Aborted
State2 --> State3 : Succeeded
State2 --> [*] : Aborted
state State3 {
state "Accumulate Enough Data\nLong State Name" as long1
long1 : Just a test
[*] --> long1
long1 --> long1 : New Data
long1 --> ProcessData : Enough Data
}
State3 --> State3 : Failed
State3 --> [*] : Succeeded / Save Result
State3 --> [*] : Aborted
\enduml
*/

23
flake.lock generated
View File

@@ -36,7 +36,28 @@
"root": {
"inputs": {
"nixpkgs": "nixpkgs",
"nixpkgs-custom-glibc": "nixpkgs-custom-glibc"
"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"
}
}
},

View File

@@ -10,12 +10,25 @@
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, ... }:
{
nixpkgs,
nixpkgs-custom-glibc,
rust-overlay,
...
}:
let
forEachSystem = import ./nix/utils.nix { inherit nixpkgs nixpkgs-custom-glibc; };
forEachSystem = import ./nix/utils.nix { inherit nixpkgs nixpkgs-custom-glibc rust-overlay; };
in
{
devShells = forEachSystem (import ./nix/devshell.nix);

View File

@@ -1,6 +1,6 @@
#pragma once
#include <boost/filesystem.hpp>
#include <filesystem>
namespace xrpl {
@@ -13,6 +13,6 @@ namespace xrpl {
* @throws runtime_error
*/
void
extractTarLz4(boost::filesystem::path const& src, boost::filesystem::path const& dst);
extractTarLz4(std::filesystem::path const& src, std::filesystem::path const& dst);
} // namespace xrpl

View File

@@ -3,6 +3,7 @@
#include <xrpl/basics/Slice.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <algorithm>
#include <cstdint>
#include <cstring>
#include <memory>
@@ -156,6 +157,19 @@ public:
}
/** @} */
/**
* Set every byte in the buffer to the given value.
*
* The size is unchanged, and this is a no-op on an empty buffer.
*
* @param value the byte to write to every position.
*/
void
fill(std::uint8_t value) noexcept
{
std::fill_n(p_.get(), size_, value);
}
/**
* Reset the buffer.
* All memory is deallocated. The resulting size is 0.
@@ -226,10 +240,4 @@ operator==(Buffer const& lhs, Buffer const& rhs) noexcept
return std::memcmp(lhs.data(), rhs.data(), lhs.size()) == 0;
}
inline bool
operator!=(Buffer const& lhs, Buffer const& rhs) noexcept
{
return !(lhs == rhs);
}
} // namespace xrpl

View File

@@ -1,24 +1,79 @@
#pragma once
#include <boost/filesystem.hpp>
#include <boost/system/error_code.hpp>
#include <cstddef>
#include <filesystem>
#include <optional>
#include <string>
#include <system_error>
namespace xrpl {
std::string
getFileContents(
boost::system::error_code& ec,
boost::filesystem::path const& sourcePath,
std::error_code& ec,
std::filesystem::path const& sourcePath,
std::optional<std::size_t> maxSize = std::nullopt);
void
writeFileContents(
boost::system::error_code& ec,
boost::filesystem::path const& destPath,
std::error_code& ec,
std::filesystem::path const& destPath,
std::string const& contents);
/**
* Generate a unique, non-existing path under @p base whose filename starts with
* @p prefix and ends with a random hex suffix.
*
* Attempts up to @p maxAttempts paths. Throws `std::runtime_error` if a unique
* path cannot be found or if the filesystem returns an error while checking for
* existence.
*/
std::filesystem::path
uniqueRandomPath(
std::filesystem::path const& base,
std::string const& prefix = "",
std::size_t maxAttempts = 100);
/**
* RAII temporary directory.
*
* The directory and all its contents are deleted when
* the instance of `TempDir` is destroyed.
*/
class TempDir
{
std::filesystem::path path_;
public:
#if !GENERATING_DOCS
TempDir(TempDir const&) = delete;
TempDir&
operator=(TempDir const&) = delete;
#endif
/**
* Construct a temporary directory.
*/
TempDir();
/**
* Destroy a temporary directory.
*/
~TempDir();
/**
* Get the native path for the temporary directory.
*/
[[nodiscard]] std::string
path() const;
/**
* Get the native path for a file.
*
* The file does not need to exist.
*/
[[nodiscard]] std::string
file(std::string const& name) const;
};
} // namespace xrpl

View File

@@ -96,9 +96,6 @@ public:
SharedIntrusive&
operator=(SharedIntrusive const& rhs);
bool
operator!=(std::nullptr_t) const;
bool
operator==(std::nullptr_t) const;

View File

@@ -111,13 +111,6 @@ SharedIntrusive<T>::operator=(SharedIntrusive<TT>&& rhs)
return *this;
}
template <class T>
bool
SharedIntrusive<T>::operator!=(std::nullptr_t) const
{
return this->get() != nullptr;
}
template <class T>
bool
SharedIntrusive<T>::operator==(std::nullptr_t) const

View File

@@ -3,8 +3,8 @@
#include <xrpl/beast/utility/Journal.h>
#include <boost/beast/core/string.hpp>
#include <boost/filesystem.hpp>
#include <filesystem>
#include <fstream>
#include <map>
#include <memory>
@@ -84,7 +84,7 @@ private:
* @return `true` if the file was opened.
*/
bool
open(boost::filesystem::path const& path);
open(std::filesystem::path const& path);
/**
* Close and re-open the system file associated with the log
@@ -133,7 +133,7 @@ private:
private:
std::unique_ptr<std::ofstream> stream_;
boost::filesystem::path path_;
std::filesystem::path path_;
};
std::mutex mutable mutex_;
@@ -152,7 +152,7 @@ public:
virtual ~Logs() = default;
bool
open(boost::filesystem::path const& pathToLogFile);
open(std::filesystem::path const& pathToLogFile);
beast::Journal::Sink&
get(std::string const& name);

View File

@@ -304,7 +304,7 @@ concept Integral64 = std::is_same_v<T, std::int64_t> || std::is_same_v<T, std::u
* on-ledger are non-negative. This is due to implementation details of
* several operations which use unsigned arithmetic internally. This is
* sufficient to represent all valid XRP values (where the absolute value
* can not exceed INITIAL_XRP: 10^17), and MPT values (where the absolute
* can not exceed kInitialXRP: 10^17), and MPT values (where the absolute
* value can not exceed maxMPTokenAmount: 2^63-1).
*
* ---- Mantissa Range Switching ----
@@ -449,12 +449,6 @@ public:
x.exponent_ == y.exponent_;
}
friend constexpr bool
operator!=(Number const& x, Number const& y) noexcept
{
return !(x == y);
}
friend constexpr bool
operator<(Number const& l, Number const& r) noexcept
{

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

@@ -85,12 +85,6 @@ public:
}
};
inline bool
operator!=(SHAMapHash const& x, SHAMapHash const& y)
{
return !(x == y);
}
template <>
inline std::size_t
extract(SHAMapHash const& key)

View File

@@ -11,6 +11,7 @@
#include <limits>
#include <stdexcept>
#include <string>
#include <string_view>
#include <type_traits>
#include <vector>
@@ -207,12 +208,6 @@ operator==(Slice const& lhs, Slice const& rhs) noexcept
return std::memcmp(lhs.data(), rhs.data(), lhs.size()) == 0;
}
inline bool
operator!=(Slice const& lhs, Slice const& rhs) noexcept
{
return !(lhs == rhs);
}
inline bool
operator<(Slice const& lhs, Slice const& rhs) noexcept
{
@@ -251,4 +246,11 @@ makeSlice(std::basic_string<char, Traits, Alloc> const& s)
return Slice(s.data(), s.size());
}
template <class Traits>
Slice
makeSlice(std::basic_string_view<char, Traits> s)
{
return Slice(s.data(), s.size());
}
} // namespace xrpl

View File

@@ -125,9 +125,31 @@ struct ParsedUrl
bool
parseUrl(ParsedUrl& pUrl, std::string const& strUrl);
/**
* Remove leading and trailing ASCII whitespace.
*
* Whitespace is the fixed set " \t\n\v\f\r"; the current locale is not
* consulted, so the result depends only on the input.
*
* @param str The string to trim.
* @return @p str without leading or trailing whitespace.
*/
std::string
trimWhitespace(std::string str);
/**
* Fold ASCII upper case letters to lower case.
*
* Only 'A' through 'Z' are remapped; every other byte is left alone and the
* current locale is not consulted, so the result depends only on the input.
*
* @param str The string to fold.
* @return @p str with each ASCII upper case letter replaced by its lower case
* equivalent.
*/
std::string
toLower(std::string str);
std::optional<std::uint64_t>
toUInt64(std::string const& s);

View File

@@ -3,6 +3,9 @@
#include <xrpl/basics/IntrusivePointer.ipp>
#include <xrpl/basics/Log.h> // IWYU pragma: keep
#include <xrpl/basics/TaggedCache.h>
#include <xrpl/basics/scope.h>
#include <algorithm>
namespace xrpl {
@@ -601,8 +604,42 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
std::vector<key_type> v;
{
std::scoped_lock const lock(mutex_);
v.reserve(cache_.size());
// Keep track of how many iterations are needed. Exit the loop if the number of retries gets
// absurd. (Note that if this somehow ever happens, one more allocation will be done under
// lock, which is undesirable, but really should be almost impossible.)
std::size_t allocationIterations = 0;
std::unique_lock lock(mutex_);
for (auto size = cache_.size(); v.capacity() < size && allocationIterations < 20;
size = cache_.size())
{
ScopeUnlock const unlock(lock);
if (allocationIterations > 0)
{
JLOG(journal_.info())
<< "getKeys(): Cache grew beyond allocated capacity after "
<< allocationIterations << " prior attempt(s). Have " << v.capacity()
<< ", need " << size << ". Retrying allocation";
}
// Allocate the current size plus a little extra, in case the cache grows while
// allocating. Each time another allocation is needed, the extra also gets bigger until
// it ultimately doubles the size + 1.
constexpr std::size_t baseShift = 5;
auto const bufferOffset = std::min(allocationIterations, std::size_t{baseShift});
auto const bufferShift = baseShift - bufferOffset;
size += (size >> bufferShift) + 1;
v.reserve(size);
++allocationIterations;
}
if (v.capacity() < cache_.size())
{
// LCOV_EXCL_START
UNREACHABLE("xrpl::TaggedCache::getKeys(): failed to allocate sufficient capacity");
v.reserve(cache_.size());
// LCOV_EXCL_STOP
}
XRPL_ASSERT(lock.owns_lock(), "xrpl::TaggedCache::getKeys(): owns lock");
XRPL_ASSERT(
v.capacity() >= cache_.size(), "xrpl::TaggedCache::getKeys(): sufficient capacity");
for (auto const& _ : cache_)
v.push_back(_.first);
}

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

@@ -116,12 +116,6 @@ public:
{
return lhs.map == rhs.map && lhs.ait == rhs.ait && lhs.mit == rhs.mit;
}
friend bool
operator!=(Iterator const& lhs, Iterator const& rhs)
{
return !(lhs == rhs);
}
};
struct ConstIterator
@@ -189,12 +183,6 @@ public:
{
return lhs.map == rhs.map && lhs.ait == rhs.ait && lhs.mit == rhs.mit;
}
friend bool
operator!=(ConstIterator const& lhs, ConstIterator const& rhs)
{
return !(lhs == rhs);
}
};
private:

View File

@@ -1038,25 +1038,6 @@ public:
Compare,
OtherAllocator> const& other) const;
template <
bool OtherIsMulti,
bool OtherIsMap,
class OtherT,
class OtherDuration,
class OtherAllocator>
bool
operator!=(AgedOrderedContainer<
OtherIsMulti,
OtherIsMap,
Key,
OtherT,
OtherDuration,
Compare,
OtherAllocator> const& other) const
{
return !(this->operator==(other));
}
template <
bool OtherIsMulti,
bool OtherIsMap,

View File

@@ -5,6 +5,7 @@
#include <xrpl/beast/container/detail/aged_associative_container.h>
#include <xrpl/beast/container/detail/aged_container_iterator.h>
#include <xrpl/beast/container/detail/empty_base_optimization.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/unordered_set.hpp>
@@ -1339,28 +1340,6 @@ public:
OtherAllocator> const& other) const
requires MaybeMulti;
template <
bool OtherIsMulti,
bool OtherIsMap,
class OtherKey,
class OtherT,
class OtherDuration,
class OtherHash,
class OtherAllocator>
bool
operator!=(AgedUnorderedContainer<
OtherIsMulti,
OtherIsMap,
OtherKey,
OtherT,
OtherDuration,
OtherHash,
KeyEqual,
OtherAllocator> const& other) const
{
return !(this->operator==(other));
}
private:
bool
wouldExceed(size_type additional) const

View File

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

View File

@@ -82,13 +82,6 @@ public:
return node_ == other.node_;
}
template <typename M>
bool
operator!=(ListIterator<M> const& other) const noexcept
{
return !((*this) == other);
}
reference
operator*() const noexcept
{

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -13,7 +13,7 @@
#include <optional>
#include <string>
namespace beast::IP {
namespace beast::ip {
using Port = std::uint16_t;
@@ -110,12 +110,6 @@ public:
operator==(Endpoint const& lhs, Endpoint const& rhs);
friend bool
operator<(Endpoint const& lhs, Endpoint const& rhs);
friend bool
operator!=(Endpoint const& lhs, Endpoint const& rhs)
{
return !(lhs == rhs);
}
friend bool
operator>(Endpoint const& lhs, Endpoint const& rhs)
{
@@ -223,7 +217,7 @@ operator<<(OutputStream& os, Endpoint const& endpoint)
std::istream&
operator>>(std::istream& is, Endpoint& endpoint);
} // namespace beast::IP
} // namespace beast::ip
//------------------------------------------------------------------------------
@@ -232,12 +226,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 +243,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

@@ -229,12 +229,6 @@ public:
return other.it_ == it_ && other.end_ == end_ && other.value_.size() == value_.size();
}
bool
operator!=(ListIterator const& other) const
{
return !(*this == other);
}
reference
operator*() const
{

View File

@@ -8,7 +8,6 @@
#include <xrpl/beast/unit_test/runner.h>
#include <xrpl/beast/unit_test/suite_info.h>
#include <boost/lexical_cast.hpp>
#include <boost/optional.hpp>
#include <algorithm>
@@ -188,7 +187,7 @@ Reporter<Unused>::fmtdur(clock_type::duration const& d)
using namespace std::chrono;
auto const ms = duration_cast<milliseconds>(d);
if (ms < seconds{1})
return boost::lexical_cast<std::string>(ms.count()) + "ms";
return std::to_string(ms.count()) + "ms";
std::stringstream ss;
ss << std::fixed << std::setprecision(1) << (ms.count() / 1000.) << "s";
return ss.str();

View File

@@ -6,11 +6,10 @@
#include <xrpl/beast/unit_test/runner.h>
#include <boost/filesystem.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/throw_exception.hpp>
#include <exception>
#include <filesystem>
#include <memory>
#include <ostream>
#include <sstream>
@@ -27,10 +26,10 @@ makeReason(String const& reason, char const* file, int line)
std::string s(reason);
if (!s.empty())
s.append(": ");
namespace fs = boost::filesystem;
namespace fs = std::filesystem;
s.append(fs::path{file}.filename().string());
s.append("(");
s.append(boost::lexical_cast<std::string>(line));
s.append(std::to_string(line));
s.append(")");
return s;
}
@@ -295,6 +294,20 @@ public:
return runner_->arg();
}
protected:
/**
* Lets a suite compose other suites (e.g. an aggregator that reruns a
* group of related suites under its own name) via `SuiteInfo::run`.
*
* @return The runner this suite is executing under.
*/
Runner&
runner() const
{
return *runner_;
}
public:
/**
* DEPRECATED
* @return `true` if the test condition indicates success(a false value)

View File

@@ -1,71 +0,0 @@
#pragma once
#include <boost/filesystem.hpp>
#include <string>
namespace beast {
/**
* RAII temporary directory.
*
* The directory and all its contents are deleted when
* the instance of `temp_dir` is destroyed.
*/
class TempDir
{
boost::filesystem::path path_;
public:
#if !GENERATING_DOCS
TempDir(TempDir const&) = delete;
TempDir&
operator=(TempDir const&) = delete;
#endif
/**
* Construct a temporary directory.
*/
TempDir()
{
auto const dir = boost::filesystem::temp_directory_path();
do
{
path_ = dir / boost::filesystem::unique_path();
} while (boost::filesystem::exists(path_));
boost::filesystem::create_directory(path_);
}
/**
* Destroy a temporary directory.
*/
~TempDir()
{
// use non-throwing calls in the destructor
boost::system::error_code ec;
boost::filesystem::remove_all(path_, ec);
// TODO: warn/notify if ec set ?
}
/**
* Get the native path for the temporary directory
*/
[[nodiscard]] std::string
path() const
{
return path_.string();
}
/**
* Get the native path for the a file.
*
* The file does not need to exist.
*/
[[nodiscard]] std::string
file(std::string const& name) const
{
return (path_ / name).string();
}
};
} // namespace beast

View File

@@ -92,10 +92,4 @@ operator==(Condition const& lhs, Condition const& rhs)
lhs.fingerprint == rhs.fingerprint;
}
inline bool
operator!=(Condition const& lhs, Condition const& rhs)
{
return !(lhs == rhs);
}
} // namespace xrpl::cryptoconditions

View File

@@ -93,12 +93,6 @@ operator==(Fulfillment const& lhs, Fulfillment const& rhs)
lhs.fingerprint() == rhs.fingerprint();
}
inline bool
operator!=(Fulfillment const& lhs, Fulfillment const& rhs)
{
return !(lhs == rhs);
}
/**
* Determine whether the given fulfillment and condition match
*/

View File

@@ -25,6 +25,7 @@ struct Sections
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 kNetworkId = "network_id";
static constexpr auto kNetworkQuorum = "network_quorum";
@@ -118,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";

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