Compare commits

..

187 Commits

Author SHA1 Message Date
Ed Hennis
f867ae0fc3 [WIP] Checkpoint 2026-06-10 19:56:08 -04:00
Ed Hennis
8ac5f8d6c4 test: Add NumberAddToNearestPicksFarther unit test 2026-06-10 17:06:15 -04:00
Ed Hennis
f38ab5fc80 Set the Guard sign correctly in += for numbers with the same exponent
- Only really relevant for negative numbers.
2026-06-10 16:41:10 -04:00
Ed Hennis
3351015c84 Add NumberAddDirectedSignWrong test, showing failure
- Addition of two negative numbers with the same exponent rounds in the
  wrong direction.
- Also include unit test cases with same exponent, and mixed signs.
  - No rounding issues in any combination, because the exponent can't
    change.
2026-06-10 16:40:44 -04:00
Ed Hennis
d8e03a8018 Update more names due to prior merge 2026-06-10 13:26:34 -04:00
Ed Hennis
e4dafa3171 Update names due to prior merge 2026-06-09 19:14:40 -04:00
Ed Hennis
1477747c37 Merge remote-tracking branch 'XRPLF/ximinez/number-round-maxrep-down' into ximinez/number-round-maxrep
* XRPLF/ximinez/number-round-maxrep-down:
  Also fix local 3_2_0 variable names
  Future proofing: Rename Large and Enabled to Large330 and Enabled330
  clang-tidy: rename MantissaScale enums from "3_2_0" to "320"
2026-06-09 19:09:39 -04:00
Ed Hennis
902fbdc3ad Also fix local 3_2_0 variable names 2026-06-09 19:06:38 -04:00
Ed Hennis
48d1c70b6c Future proofing: Rename Large and Enabled to Large330 and Enabled330
- If more fixes need to be made in the future, they can be added after,
  instead of needing to do the "rename dance", I had to do with this PR.
2026-06-09 18:44:46 -04:00
Ed Hennis
66ff72f56d clang-tidy: rename MantissaScale enums from "3_2_0" to "320" 2026-06-09 18:38:03 -04:00
Ed Hennis
4139ebbe6b Fix issues introduced by prior merge, and new MantissaRange 2026-06-09 18:31:59 -04:00
Ed Hennis
9924b6ce65 Merge remote-tracking branch 'XRPLF/ximinez/number-round-maxrep-down' into ximinez/number-round-maxrep
* XRPLF/ximinez/number-round-maxrep-down:
  Clean up the "New" names
  Update to use a new amendment, since this PR will not be part of 3.2.0
  fix: Fix Number comparison operator (7406)
  feat: Use C++ 23 standard (7431)
  refactor: Introduce XRPL_ASSERT_IF for amendment-gated assertions (7378)
  refactor: Change config section and key string literals into constants (7095)
  refactor: Use `std::move` and `std::string_view` where possible (7424)
  refactor: Use const function arguments where possible (7423)
  ci: Use XRPLF/actions build-multiarch-image workflow (7428)
  ci: Use new packaging images and don't cancel develop builds (7417)
  ci: [DEPENDABOT] bump codecov/codecov-action from 6.0.1 to 7.0.0 (7426)
2026-06-09 18:08:04 -04:00
Ed Hennis
63f1a40b77 Clean up the "New" names 2026-06-09 17:06:27 -04:00
Ed Hennis
5bafceefaf Merge remote-tracking branch 'XRPLF/develop' into ximinez/number-round-maxrep-down
* XRPLF/develop:
  fix: Fix Number comparison operator (7406)
  feat: Use C++ 23 standard (7431)
  refactor: Introduce XRPL_ASSERT_IF for amendment-gated assertions (7378)
2026-06-09 16:51:38 -04:00
Ed Hennis
44f3011b9b Merge remote-tracking branch 'XRPLF/develop' into ximinez/number-round-maxrep-down
* XRPLF/develop:
  refactor: Change config section and key string literals into constants (7095)
  refactor: Use `std::move` and `std::string_view` where possible (7424)
  refactor: Use const function arguments where possible (7423)
  ci: Use XRPLF/actions build-multiarch-image workflow (7428)
  ci: Use new packaging images and don't cancel develop builds (7417)
  ci: [DEPENDABOT] bump codecov/codecov-action from 6.0.1 to 7.0.0 (7426)
2026-06-09 16:45:02 -04:00
Ed Hennis
d9c63cb9bc Update to use a new amendment, since this PR will not be part of 3.2.0
- This requires creating yet another MantissaScale, and CuspRoundingFix
  option.
2026-06-09 16:44:13 -04:00
Ed Hennis
2cbc3c139e fix: Fix Number comparison operator (#7406) 2026-06-09 17:46:56 +00:00
Ayaz Salikhov
fccb109e48 feat: Use C++ 23 standard (#7431) 2026-06-09 17:36:17 +00:00
Vito Tumas
0fb1aca461 refactor: Introduce XRPL_ASSERT_IF for amendment-gated assertions (#7378)
Co-authored-by: xrplf-ai-reviewer[bot] <266832837+xrplf-ai-reviewer[bot]@users.noreply.github.com>
2026-06-09 17:02:06 +00:00
Bart
c552eb333f refactor: Change config section and key string literals into constants (#7095)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
2026-06-09 14:58:21 +00:00
Bart
c9769d1add refactor: Use std::move and std::string_view where possible (#7424)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
2026-06-09 13:56:32 +00:00
Bart
ee9fbc4e08 refactor: Use const function arguments where possible (#7423)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
2026-06-09 10:04:09 +00:00
Ed Hennis
12741a247a Cleanups, mostly from previous merge, plus a few outdated comments 2026-06-08 20:21:38 -04:00
Ed Hennis
85980aec6a Fix broken unit tests 2026-06-08 19:44:44 -04:00
Ed Hennis
6da1f224f8 Merge remote-tracking branch 'XRPLF/ximinez/number-round-maxrep-down' into ximinez/number-round-maxrep
* XRPLF/ximinez/number-round-maxrep-down:
  clang-tidy: Guard public member variable names; Missing include
  Clean up tests
2026-06-08 19:43:20 -04:00
Ed Hennis
5bccfe2b6d clang-tidy: Guard public member variable names; Missing include 2026-06-08 19:03:53 -04:00
Ed Hennis
308e46d0da Clean up tests 2026-06-08 19:00:24 -04:00
Ayaz Salikhov
577d7457f1 ci: Use XRPLF/actions build-multiarch-image workflow (#7428) 2026-06-08 17:10:05 +00:00
Ayaz Salikhov
a389f922dd ci: Use new packaging images and don't cancel develop builds (#7417)
Co-authored-by: Bart <bthomee@users.noreply.github.com>
2026-06-08 13:41:08 +00:00
dependabot[bot]
79f4ddc4a6 ci: [DEPENDABOT] bump codecov/codecov-action from 6.0.1 to 7.0.0 (#7426)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-08 09:37:50 +00:00
Ed Hennis
f9183aa34a Merge remote-tracking branch 'XRPLF/ximinez/number-round-maxrep-down' into ximinez/number-round-maxrep
* XRPLF/ximinez/number-round-maxrep-down:
  Reorganize the subtraction tests
2026-06-07 16:21:45 -04:00
Ed Hennis
fe64b99147 Reorganize the subtraction tests 2026-06-06 16:20:51 -04:00
Ed Hennis
121786aada Merge remote-tracking branch 'XRPLF/ximinez/number-round-maxrep-down' into ximinez/number-round-maxrep
* XRPLF/ximinez/number-round-maxrep-down:
  Fix formatting, add an assert
2026-06-06 16:02:59 -04:00
Ed Hennis
d7ce0e2dd3 Fix formatting, add an assert 2026-06-06 15:38:29 -04:00
Ed Hennis
b2cea736d0 Merge branch 'ximinez/number-round-maxrep-down' into ximinez/number-round-maxrep
* ximinez/number-round-maxrep-down:
  Revert "Rollback Number class changes; show the fix works without side effects"
  Rollback Number class changes; show the fix works without side effects
  Include rounding in failed unit tests
  Improve comment descriptions
  Rework subtraction rounding (again) for more accuracy
  build: Create single test binary xrpl_tests (7327)
  ci: [DEPENDABOT] bump actions/checkout from 6.0.2 to 6.0.3 (7414)
  ci: Refactor build-related nix / docker / workflows (7408)
  refactor: Construct Number::Guard from MantissaRange or relevant fields
  ci: Use multiple directories in dependabot config (7413)
  ci: Update clang-tidy to nix-based v22 (7412)
  clang-tidy: template param names, const correctness, braces
2026-06-06 15:25:56 -04:00
Ed Hennis
c165af497e Revert "Rollback Number class changes; show the fix works without side effects"
This reverts commit 8743be8eae.
2026-06-06 14:35:35 -04:00
Ed Hennis
8743be8eae Rollback Number class changes; show the fix works without side effects 2026-06-06 14:34:31 -04:00
Ed Hennis
3a5c85067a Include rounding in failed unit tests 2026-06-06 14:33:31 -04:00
Ed Hennis
2f701121b4 Merge remote-tracking branch 'upstream/develop' into ximinez/number-round-maxrep-down
* upstream/develop:
  build: Create single test binary xrpl_tests (7327)
  ci: [DEPENDABOT] bump actions/checkout from 6.0.2 to 6.0.3 (7414)
  ci: Refactor build-related nix / docker / workflows (7408)
  ci: Use multiple directories in dependabot config (7413)
  ci: Update clang-tidy to nix-based v22 (7412)
2026-06-06 14:04:24 -04:00
Ed Hennis
961ac6671e Improve comment descriptions 2026-06-06 13:09:52 -04:00
Ed Hennis
012c67a7eb Rework subtraction rounding (again) for more accuracy
- Go back to the old method of computing the mantissa, but when post
  processing, expand the mantissa to slightly larger than maxMantissa,
  then in doRoundDown, if the result is not exact, subtract one.
  Finally, let doNormalize figure out the rounding of the result.
2026-06-06 01:04:26 -04:00
Ayaz Salikhov
949887feb9 build: Create single test binary xrpl_tests (#7327) 2026-06-05 19:24:32 +00:00
dependabot[bot]
fc57dab78b ci: [DEPENDABOT] bump actions/checkout from 6.0.2 to 6.0.3 (#7414)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-05 17:17:47 +00:00
Ayaz Salikhov
63ffdc39dc ci: Refactor build-related nix / docker / workflows (#7408) 2026-06-05 17:05:19 +00:00
Ed Hennis
74c66d0944 refactor: Construct Number::Guard from MantissaRange or relevant fields
- Simplifies the function signatures in Guard, because it doesn't need
  to have those values passed in constantly.
- Also simplifies some of the functions because they don't need to store
  values just to pass them to Guard functions.
2026-06-05 12:06:41 -04:00
Ayaz Salikhov
6571f75d39 ci: Use multiple directories in dependabot config (#7413) 2026-06-05 14:36:05 +00:00
Ayaz Salikhov
2111bb4b95 ci: Update clang-tidy to nix-based v22 (#7412) 2026-06-05 14:11:47 +00:00
Ed Hennis
f1bb4ded21 clang-tidy: template param names, const correctness, braces 2026-06-04 20:05:53 -04:00
Ed Hennis
e1295d1ce8 Merge branch 'ximinez/number-round-maxrep-down' into ximinez/number-round-maxrep 2026-06-04 19:03:43 -04:00
Ed Hennis
aa8888732e Merge branch 'develop' into ximinez/number-round-maxrep-down 2026-06-04 19:03:32 -04:00
Ed Hennis
50c0d9f2b0 Handle a whole bunch of edge cases
- Add more tests
2026-06-04 18:53:50 -04:00
Ayaz Salikhov
8abe82eefa ci: Redesign matrix configuration based on Nix images (#7385)
Co-authored-by: semgrep-companion-app[bot] <218312740+semgrep-companion-app[bot]@users.noreply.github.com>
2026-06-04 20:02:59 +00:00
Ayaz Salikhov
5b8e6cd1dd test: Fix LCOV_EXCL_END -> LCOV_EXCL_STOP (#7407) 2026-06-04 19:35:36 +00:00
Ed Hennis
b5574baa36 Add line numbers to Number::to_string test 2026-06-04 14:40:39 -04:00
Ed Hennis
015d9a6cb9 Round mantissas between kMaxRep and kMaxRepUp
- Treat values in between kMaxRep (2^63-1) and kMaxRepUp (((kMaxRep
  / 10) + 1) * 10, which is the next multiple of 10 above kMaxRep) as if
  those values were sequential, and values in between were "fractional".
- This results in values above the midpoint rounding up to kMaxRepUp,
  and below the midpoint to kMaxRep when rounding to nearest. Other
  rounding modes act along the same lines.
- Also refactor "Number::Guard::round()` to return an enum making it
  clearer what's going on.
2026-06-04 14:14:01 -04:00
Ayaz Salikhov
12e81abef3 ci: Improve sanitizer-libs, add doxygen, dpkg, rpm in nix (#7403) 2026-06-04 14:52:42 +00:00
Ayaz Salikhov
6c543426c3 ci: Fix clang asan include dirs in nix images, add curl & gnupg (#7400) 2026-06-03 22:19:15 +00:00
yinyiqian1
e5cf1a0985 fix: Add zero NFT Offer ID check for NFTokenCancelOffer (#7391) 2026-06-03 19:30:20 +00:00
Ayaz Salikhov
023bdaeeed ci: Install gcov, nettools, cacert in nix images (#7398) 2026-06-03 19:14:17 +00:00
Bart
96b2c0964f refactor: Replace intr_ptr::SharedPtr<SHAMapTreeNode> by SHAMapTreeNodePtr (#7396)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
2026-06-03 15:34:19 +00:00
Ayaz Salikhov
1441d4690d chore: Update flake.lock to allow conan with clang-22 support (#7390) 2026-06-03 00:16:02 +00:00
Ed Hennis
51902cd6b4 Revert "Remove the kMaxRep+1 rounding tests"
This reverts commit c84939ccea.
2026-06-02 16:03:08 -04:00
Ed Hennis
c84939ccea Remove the kMaxRep+1 rounding tests 2026-06-02 15:59:26 -04:00
Ed Hennis
9e8c3caef4 Improve accuracy of Number::operator+=
- Use more of the available range of the uint128 operands.
- Also refactor Number::Guard::round() to return an enum.
2026-06-02 15:35:42 -04:00
Vito Tumas
225ed204ad test: Suppress invariant-failure logs in Vault and LoanBroker bug-regression tests (#7379) 2026-06-02 17:12:09 +00:00
Ayaz Salikhov
ad111bcc22 ci: Patch binaries in nix-based images and test in every distro (#7376)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-02 13:51:20 +00:00
Ed Hennis
35bee87909 Experimental: Scale addition operands up to preserve accuracy 2026-06-01 21:52:31 -04:00
Ed Hennis
261508a0ec Merge remote-tracking branch 'XRPLF/develop' into ximinez/number-round-maxrep-down
* XRPLF/develop:
  ci: Check binaries separately from building them (7355)
  ci: [DEPENDABOT] bump eps1lon/actions-label-merge-conflict from 3.0.3 to 3.1.0 (7375)
  refactor: Use `STLedgerEntry` type aliases instead of `std::shared_ptr` (7282)
  fix: Adjust xrpld systemd service and update timer (7374)
  release: Bump version to 3.2.0-rc3 (7371)
  fix: Pin overpayment principal reduction to exact on-grid value (7360)
  fix: Improve upward rounding edge cases for Number::operator/= (7328)
  refactor: Revert "perf: Remove unnecessary caches (5439)" (7359)
  fix: Add zero domainID check for permissionedDomain (7362)
2026-06-01 15:33:34 -04:00
Ayaz Salikhov
d4cb68d5a1 ci: Check binaries separately from building them (#7355)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-01 16:47:01 +00:00
dependabot[bot]
e209ee5371 ci: [DEPENDABOT] bump eps1lon/actions-label-merge-conflict from 3.0.3 to 3.1.0 (#7375)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-01 15:29:12 +00:00
Vito Tumas
109b649106 refactor: Use STLedgerEntry type aliases instead of std::shared_ptr (#7282) 2026-06-01 15:27:13 +00:00
Michael Legleux
0fffe23abc fix: Adjust xrpld systemd service and update timer (#7374) 2026-06-01 03:33:19 +00:00
Bart
7e15621e7b release: Bump version to 3.2.0-rc3 (#7371)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
2026-05-31 22:55:18 +00:00
Vito Tumas
99431d7833 fix: Pin overpayment principal reduction to exact on-grid value (#7360) 2026-05-31 22:54:23 +00:00
Ed Hennis
47365f4220 fix: Improve upward rounding edge cases for Number::operator/= (#7328)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Vito Tumas <5780819+Tapanito@users.noreply.github.com>
2026-05-31 00:23:29 +00:00
Bart
1599c1a672 refactor: Revert "perf: Remove unnecessary caches (#5439)" (#7359)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
2026-05-30 18:48:59 +00:00
yinyiqian1
763dd503be fix: Add zero domainID check for permissionedDomain (#7362) 2026-05-30 00:16:25 +00:00
Ed Hennis
9f872f2179 Include upward, write tests based on "expected" behavior 2026-05-29 19:46:50 -04:00
Ed Hennis
d1af39d9dd test: Add another rounding unit test 2026-05-29 19:03:34 -04:00
Ed Hennis
f6a26ca34f CI feedback: Add test cases covering other rounding modes
- Downward with a negative result, and ToNearest with a remainder
  slightly larger than 0.5.
2026-05-29 18:54:08 -04:00
Ed Hennis
c0569037f8 Apply suggestions from code review
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-29 16:34:51 -04:00
Ed Hennis
be9ae88d48 Accept AI suggestion
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-28 23:38:54 -04:00
Ed Hennis
cd21d74538 Update the testUpwardRoundsDown test to run under all scales
- Demonstrates the incorrect "before" behavior
2026-05-28 19:58:52 -04:00
Ed Hennis
2fdfd2b420 Review feedback from Tapanito and AI
- Add missing headers.
- Improve code coverage exclusions.
- Clean up several variable names.
- Improve explanatory comments.
- Remove the switch statement from MantissaRange::getMin. Change it to
  a straight power of ten lookup.
2026-05-28 18:41:19 -04:00
Ed Hennis
06a3f76ccd Skip clang-tidy false positive: misc-include-cleaner 2026-05-28 17:47:41 -04:00
Ed Hennis
dadf4d737d Merge branch 'develop' into ximinez/number-division-accuracy 2026-05-28 17:46:40 -04:00
Bart
2f3558c610 ci: Run PR title and description checks on staging and release branches (#7331)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
2026-05-28 14:57:29 +00:00
Ed Hennis
7b66b42713 Merge branch 'develop' into ximinez/number-division-accuracy 2026-05-27 17:00:59 -04:00
Ayaz Salikhov
f9551ac5ca style: Run shfmt on workflows, actions and markdown bash code (#7333) 2026-05-27 19:24:18 +00:00
Ed Hennis
18ac8a0583 Merge branch 'develop' into ximinez/number-division-accuracy 2026-05-27 15:18:17 -04:00
Bart
1acc42313c release: Bump version to 3.2.0-rc2 (#7348) 2026-05-27 15:11:38 -04:00
Bart
396d772a15 refactor: Enable support for fixCleanup3_2_0 amendment (#7347) 2026-05-27 19:10:33 +00:00
Ayaz Salikhov
1438bf1c67 release: Bump version to 3.2.0-rc1 (#7335) 2026-05-27 13:20:57 -04:00
Ed Hennis
de2efa5cb9 Remove TMax entirely from normalizeToRange; check type matching directly 2026-05-27 13:06:52 -04:00
Ed Hennis
8dcd88e83c Tweak how the denominator is handled in division
- Removes one int64 to 128 conversion
2026-05-27 12:34:49 -04:00
Ed Hennis
5333422402 Merge remote-tracking branch 'XRPLF/develop' into ximinez/number-division-accuracy
* XRPLF/develop:
  fix: Fix a rounding error at the `Number::maxRep` cusp (7051)
2026-05-27 12:17:30 -04:00
Ed Hennis
4ec049e727 Minor fixes: missing include, variable init, typo 2026-05-27 12:09:13 -04:00
Ed Hennis
7da643d864 fix: Fix a rounding error at the Number::maxRep cusp (#7051)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Vito Tumas <5780819+Tapanito@users.noreply.github.com>
2026-05-27 15:19:20 +00:00
Ed Hennis
ae9c72bb7c Test optimization: Number_test::pow10 2026-05-27 00:36:38 -04:00
Ed Hennis
5abecb9fcb Significant rewrite
- Simplify Number::operator/= to use more constexpr values, and fewer
  variations.
  - Most significantly, rounding up doesn't need more precision, it only
    needs to know if there's a remainder after the current precision work
    is done. Tracked similarly Guard::xbit_.
- Build a constexpr lookup array for powers of 10. Only a handful of
  values are used, but since it's built at compile time, and constexpr,
  unused values do not affect memory or performance.
2026-05-27 00:07:48 -04:00
Ed Hennis
12670b0c3f Merge branch 'ximinez/number-fix-maxrepcusp' into ximinez/number-division-accuracy 2026-05-26 19:21:05 -04:00
Ed Hennis
1e7876a03c Merge branch 'develop' into ximinez/number-fix-maxrepcusp 2026-05-26 19:21:01 -04:00
Ed Hennis
e851e80de0 Merge branch 'ximinez/number-fix-maxrepcusp' into ximinez/number-division-accuracy 2026-05-26 16:56:47 -04:00
Ed Hennis
a963035f76 Merge branch 'develop' into ximinez/number-fix-maxrepcusp 2026-05-26 16:56:43 -04:00
Ayaz Salikhov
1162371def ci: Only push docker images in XRPLF/rippled (#7330) 2026-05-26 20:03:04 +00:00
Ed Hennis
8ab904de57 Merge branch 'ximinez/number-fix-maxrepcusp' into ximinez/number-division-accuracy 2026-05-26 16:01:44 -04:00
Ed Hennis
100ec464d9 Merge branch 'develop' into ximinez/number-fix-maxrepcusp 2026-05-26 16:01:40 -04:00
Ed Hennis
e89e6f50e8 Merge remote-tracking branch 'XRPLF/ximinez/number-fix-maxrepcusp' into ximinez/number-division-accuracy
* XRPLF/ximinez/number-fix-maxrepcusp:
  clang-tidy: implicit bool conversion
  Address some AI review feedback: predeclare, include, format, comment
  fix: Fix `VaultInvariant` and `VaultDeposit` precision bugs at IOU scale boundaries (7272)
  ci: Add clang to nix images (7308)
  fix: Include management-fee delta in doOverpayment assertion (7039)
  fix: Fix clang-tidy pre-commit hook to locate compile_commands.json from repo root (7325)
  fix: Use consistent scale for `debtTotal` (7093)
  fix: Skip deleted book directories and non-root modifications in `ValidBookDirectory` invariant (7312)
  fix: Address review feedback on FD/handle guarding (5823 follow-up) (7310)
  fix: Fix non-canonical MPT amount (7117)
2026-05-26 15:53:36 -04:00
Ed Hennis
27456fa439 Use the local range instead of calling a function 2026-05-26 15:52:25 -04:00
Ed Hennis
d6844311c0 clang-tidy: missing header 2026-05-26 15:48:29 -04:00
dependabot[bot]
2a0feca46b ci: [DEPENDABOT] bump docker/setup-buildx-action from 4.0.0 to 4.1.0 (#7322)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-26 19:36:32 +00:00
dependabot[bot]
108a4c8217 ci: [DEPENDABOT] bump codecov/codecov-action from 6.0.0 to 6.0.1 (#7321)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-26 19:36:21 +00:00
dependabot[bot]
4584b01bde ci: [DEPENDABOT] bump docker/build-push-action from 7.1.0 to 7.2.0 (#7320)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-26 19:36:13 +00:00
dependabot[bot]
7c59786565 ci: [DEPENDABOT] bump docker/metadata-action from 6.0.0 to 6.1.0 (#7319)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-26 19:36:00 +00:00
dependabot[bot]
9623e67b76 ci: [DEPENDABOT] bump docker/login-action from 4.1.0 to 4.2.0 (#7318)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-26 19:35:52 +00:00
Andrzej Budzanowski
85af406a0f fix: Update clang-tidy to include src/tests directory header check (#7307) 2026-05-26 19:35:32 +00:00
Ed Hennis
fbee0349f5 clang-tidy: implicit bool conversion 2026-05-26 15:21:42 -04:00
Ayaz Salikhov
ac33fb32a7 chore: Pin Python packages for codegen using uv (#7329) 2026-05-26 18:35:38 +00:00
Ayaz Salikhov
23d0812827 style: Use shfmt instead of bashate (#7326) 2026-05-26 18:28:23 +00:00
Vito Tumas
49567e7283 fix: Fix edge-case where vault-depositor may get stuck (#7139) 2026-05-26 18:18:40 +00:00
Ed Hennis
84ca271d95 Address some AI review feedback: predeclare, include, format, comment
- Predeclare type reference in Rules.h
- Remove an unneeded include in EscrowToken_test
- Number_test will format negative BigInts correctly (unused)
- Remove an inaccurate comment
2026-05-26 13:51:06 -04:00
Ed Hennis
75dfc65f5f Merge branch 'develop' into ximinez/number-fix-maxrepcusp 2026-05-26 13:47:33 -04:00
Vito Tumas
633ef4706f fix: Fix VaultInvariant and VaultDeposit precision bugs at IOU scale boundaries (#7272)
Co-authored-by: Bart <bthomee@users.noreply.github.com>
2026-05-26 16:32:44 +00:00
Ayaz Salikhov
49cb3f45a4 ci: Add clang to nix images (#7308)
Co-authored-by: semgrep-companion-app[bot] <218312740+semgrep-companion-app[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-26 15:45:33 +00:00
Vito Tumas
22a21b175e fix: Include management-fee delta in doOverpayment assertion (#7039) 2026-05-26 14:01:52 +00:00
Pratik Mankawde
e9d885bd9b fix: Fix clang-tidy pre-commit hook to locate compile_commands.json from repo root (#7325)
Signed-off-by: Pratik Mankawde <3397372+pratikmankawde@users.noreply.github.com>
2026-05-26 13:50:18 +00:00
Jingchen
a911f9089e fix: Use consistent scale for debtTotal (#7093)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-24 20:44:29 +00:00
Peter Chen
e34c2667d7 fix: Skip deleted book directories and non-root modifications in ValidBookDirectory invariant (#7312) 2026-05-24 20:37:16 +00:00
Ed Hennis
48b1716e6f Make Number::operator/= significantly more accurate
- Prevents extreme dust rounding from getting lost, especially when
  rounding away from zero. (Upward for positive, downward for negative.)
2026-05-23 19:02:03 +01:00
Valentin Balaschenko
30de556224 fix: Address review feedback on FD/handle guarding (#5823 follow-up) (#7310) 2026-05-23 14:48:48 +00:00
Gregory Tsipenyuk
dcd2ff0b5f fix: Fix non-canonical MPT amount (#7117)
Co-authored-by: xrplf-ai-reviewer[bot] <266832837+xrplf-ai-reviewer[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-23 06:40:26 +00:00
Ed Hennis
4ab886bcbc Merge branch 'develop' into ximinez/number-fix-maxrepcusp 2026-05-22 17:56:15 -04:00
Bart
dfb9b8ed9a release: Bump version to 3.2.0-b7 (#7316)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
2026-05-22 19:32:12 +00:00
Jingchen
179e73594a fix: Check if the MPT first loss cover can be sent to the broker before deleting the broker (#7125)
Co-authored-by: xrplf-ai-reviewer[bot] <266832837+xrplf-ai-reviewer[bot]@users.noreply.github.com>
2026-05-22 11:58:48 +00:00
Michael Legleux
15dd653e4b fix: Fix RPM prerelease ordering and start xrpld on DEB install (#7313) 2026-05-22 11:30:45 +00:00
Michael Legleux
a37afe13ff ci: Re-enable full nproc for Linux (#7315) 2026-05-22 11:30:37 +00:00
Gregory Tsipenyuk
3547a9335f fix: Add assorted MPT/DEX fixes (#7040)
Co-authored-by: xrplf-ai-reviewer[bot] <266832837+xrplf-ai-reviewer[bot]@users.noreply.github.com>
Co-authored-by: Shawn Xie <35279399+shawnxie999@users.noreply.github.com>
2026-05-21 18:29:53 +00:00
Ed Hennis
7f64c337d8 Merge branch 'develop' into ximinez/number-fix-maxrepcusp 2026-05-21 14:25:50 -04:00
Bart
1a98182e23 refactor: Remove dead fetchBatch code (#7309)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
2026-05-21 17:52:41 +00:00
Bart
79308705c5 release: Bump version to 3.2.0-b6 (#7311)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
2026-05-21 17:50:59 +00:00
Vito Tumas
e24de65f42 chore: Revert graceful peer disconnection and follow-up fix (#7296) 2026-05-21 16:13:41 +00:00
Vito Tumas
7fdaa0a5ef fix: Fix IOU precision issues in LoanBrokerCover transactions (#7274) 2026-05-21 14:51:58 +00:00
Vito Tumas
795dc5e364 fix: Avoid principal-zeroing in non-final loan payments at coarse scale (#7050)
Co-authored-by: Ed Hennis <ed@ripple.com>
2026-05-21 14:46:26 +00:00
Ed Hennis
61bdd6fb78 Merge branch 'develop' into ximinez/number-fix-maxrepcusp 2026-05-21 10:10:00 -04:00
Pratik Mankawde
f6fd5ddb0a fix: Add null check (#7305)
Signed-off-by: Pratik Mankawde <3397372+pratikmankawde@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-21 13:24:04 +00:00
Ed Hennis
8e06e78f11 Merge branch 'develop' into ximinez/number-fix-maxrepcusp 2026-05-21 07:11:49 -04:00
Ed Hennis
42fda85fbc Fix more AMM tests, and to not exclude fixCleanup3_2_0 2026-05-21 12:04:29 +01:00
Rithvik Reddygari
afcf6fbcdc docs: Add --parallel flag to cmake build commands in BUILD.md (#7302) 2026-05-21 06:33:19 +00:00
Shawn Xie
28cc20c816 fix: Fix wrong hybrid offer orderbook placement and update LedgerStateFix to amend ExchangeRate meta (#7087)
Co-authored-by: Peter Chen <ychen@ripple.com>
2026-05-21 06:19:04 +00:00
Ed Hennis
3a4b92b050 Change the priority of the amendments for large mantissas
- Order the checks so that large mantissa is only enabled if SAV or LP
  are enabled. fixCleanup3_2_0 only enables the rounding fix.
- Fix tests, and don't exclude fixCleanup3_2_0 in AMM tests
- Also fix formatting
2026-05-21 00:53:07 +01:00
Ed Hennis
aea19df3c1 Apply suggestions from @Tapanito code review
Co-authored-by: Vito Tumas <5780819+Tapanito@users.noreply.github.com>
2026-05-20 18:46:17 -04:00
Ed Hennis
8b56749ca3 Apply suggestions from Copilot code review
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-20 18:39:46 -04:00
Ed Hennis
71cf996fc6 Review feedback from @tapanito: lambda checks condition in doRoundUp 2026-05-20 23:28:26 +01:00
Alex Kremer
a830ab10ef style: More clang-tidy identifier renaming (#7290) 2026-05-20 21:31:15 +00:00
Shawn Xie
8c0080020f fix: Update pDEX invariant firing under a valid offer deletion (#7118)
Co-authored-by: Peter Chen <ychen@ripple.com>
2026-05-20 21:10:04 +00:00
yinyiqian1
9cb0740673 fix: Fix multisign and signfor to check for delegate (#7064) 2026-05-20 20:24:09 +00:00
Mayukha Vadari
242ce3e9e4 refactor: Fix sfGeneric and sfInvalid field names (#7300) 2026-05-20 19:47:59 +00:00
box4wangjing
a5d238e7d4 docs: Fix some comments to improve readability (#7122)
Signed-off-by: box4wangjing <box4wangjing@outlook.com>
Co-authored-by: Mayukha Vadari <mvadari@ripple.com>
2026-05-20 19:46:45 +00:00
Vito Tumas
9cb049276d feat: Propagate underlying MPT flags to vault shares (#7077)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Denis Angell <dangell@transia.co>
Co-authored-by: Fomo <508629+shortthefomo@users.noreply.github.com>
Co-authored-by: Bart <bthomee@users.noreply.github.com>
Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-20 19:44:09 +00:00
Ed Hennis
4c7ea64b6c Merge branch 'develop' into ximinez/number-fix-maxrepcusp 2026-05-19 16:53:33 -04:00
Ed Hennis
c8947c6f75 Merge branch 'develop' into ximinez/number-fix-maxrepcusp 2026-05-19 10:15:10 -04:00
Ed Hennis
09ae5b719f Merge branch 'develop' into ximinez/number-fix-maxrepcusp 2026-05-19 05:15:47 -04:00
Ed Hennis
09f2d06dd4 Merge branch 'develop' into ximinez/number-fix-maxrepcusp 2026-05-15 21:32:09 -04:00
Ed Hennis
6964013941 Merge remote-tracking branch 'XRPLF/develop' into ximinez/number-fix-maxrepcusp
* XRPLF/develop:
  release: Set version to 3.3.0-b0 (7280)
  refactor: Rename static constants (7120)
  refactor: Use `isFlag` where possible instead of bitwise math (7278)
  ci: Update XRPLF/actions (7281)
2026-05-15 21:14:34 -04:00
Ed Hennis
70c6e01d7e clang-tidy: this is ridiculous 2026-05-14 21:02:49 -04:00
Ed Hennis
ddfb7ee69c clang-tidy: {} 2026-05-14 20:48:34 -04:00
Ed Hennis
b69b9242e2 fixup! clang-tidy: Avoid nested "?:" in global Rules initialization 2026-05-14 20:33:15 -04:00
Ed Hennis
cd2fcf0a5e Merge branch 'develop' into ximinez/number-fix-maxrepcusp 2026-05-14 18:25:17 -04:00
Ed Hennis
69656d6b67 clang-tidy: Avoid nested "?:" in global Rules initialization 2026-05-14 18:24:05 -04:00
Ed Hennis
46b946b22e clang-tidy: missing include 2026-05-13 22:32:37 -04:00
Ed Hennis
ae03b30f29 Merge branch 'develop' into ximinez/number-fix-maxrepcusp 2026-05-13 20:16:19 -04:00
Ed Hennis
4c7c019add Merge branch 'develop' into ximinez/number-fix-maxrepcusp 2026-05-13 12:03:35 -04:00
Ed Hennis
47f30c913d Fix broken unit tests: EscrowToken
- Some EscrowToken tests used a hard-coded list of amendments to
  determine whether to expect large mantissa logic. That ignored the
  effects of fixCleanup3_2_0, especially as applied to the previous fix
  affecting preflight, preclaim, etc.
- Add a helper function, useRulesGuards, which will return the same
  decision as createGuards and setCurrentRulesImpl. Use that helper
  function in the relevant tests.
- Also remove an #include that clang-tidy was complaining about.
2026-05-12 21:26:54 -04:00
Ed Hennis
d7d5b83f6d Merge branch 'develop' into ximinez/number-fix-maxrepcusp 2026-05-12 19:18:45 -04:00
Ed Hennis
e22938d69f AI review feedback: createGuards
- Refactor the Guard decision in withTxnType into createGuards, which
  lives in Rules.cpp. It is physically located near
  setCurrentTransactionRules, and documented to explain that changes
  need to be synchronized.
2026-05-12 18:44:05 -04:00
Ed Hennis
7c9a56ff24 Merge branch 'develop' into ximinez/number-fix-maxrepcusp 2026-05-12 16:26:09 -04:00
Ed Hennis
5a40416673 Merge branch 'develop' into ximinez/number-fix-maxrepcusp 2026-05-12 15:59:19 -04:00
Ed Hennis
30334cd1f4 Merge branch 'develop' into ximinez/number-fix-maxrepcusp 2026-05-11 13:34:11 -04:00
Ed Hennis
5558e1b522 Merge branch 'develop' into ximinez/number-fix-maxrepcusp 2026-05-07 18:10:03 -04:00
Ed Hennis
cd0f49a003 Address more nitpicky AI comments 2026-05-07 17:05:10 -04:00
Ed Hennis
22d2703ce8 What is it going to take to get clang-tidy to shut up? 2026-05-07 16:50:43 -04:00
Ed Hennis
d03274b731 Merge branch 'develop' into ximinez/number-fix-maxrepcusp 2026-05-07 14:18:28 -04:00
Ed Hennis
1b6047afe1 More clang-tidy changes: AMMExtended_test member and Number_test includes 2026-05-07 13:51:48 -04:00
Ed Hennis
175a04160d Merge branch 'develop' into ximinez/number-fix-maxrepcusp 2026-05-07 13:28:33 -04:00
Ed Hennis
b050c151f8 Fix clang-tidy issues, and more AI complaints 2026-05-06 23:26:11 -04:00
Ed Hennis
a2b21d75ce Fix AI-identified mistakes 2026-05-06 22:56:07 -04:00
Ed Hennis
b40d2a8e7d fix: Fix a rounding error at the Number::maxRep cusp
- Add helper function, doDropDigit, to wrap the common pattern:
    push(mantissa % 10);
    mantissa /= 10;
    ++exponent;
- Might have been helpful to catch this issue when developing.
2026-05-06 22:49:44 -04:00
733 changed files with 19855 additions and 10468 deletions

View File

@@ -153,8 +153,8 @@ Checks: "-*,
readability-use-std-min-max
"
# ---
# readability-inconsistent-declaration-parameter-name, # in this codebase this check will break a lot of arg names
# readability-static-accessed-through-instance, # this check is probably unnecessary. it makes the code less readable
# readability-inconsistent-declaration-parameter-name, # In this codebase this check will break a lot of arg names
# readability-static-accessed-through-instance, # this check is probably unnecessary. It makes the code less readable
# ---
CheckOptions:
@@ -191,11 +191,14 @@ CheckOptions:
readability-identifier-naming.ParameterCase: camelBack
readability-identifier-naming.FunctionCase: camelBack
readability-identifier-naming.MemberCase: camelBack
readability-identifier-naming.PrivateMemberCase: camelBack
readability-identifier-naming.PrivateMemberSuffix: _
readability-identifier-naming.ProtectedMemberCase: camelBack
readability-identifier-naming.ProtectedMemberSuffix: _
readability-identifier-naming.PublicMemberCase: camelBack
readability-identifier-naming.PublicMemberSuffix: ""
readability-identifier-naming.GlobalFunctionIgnoredRegexp: "^(to_string|hash_append|tuple_hash)$"
HeaderFilterRegex: '^.*/(test|xrpl|xrpld)/.*\.(h|hpp|ipp)$'
HeaderFilterRegex: '^.*/(tests?|xrpl|xrpld)/.*\.(h|hpp|ipp)$'
ExcludeHeaderFilterRegex: '^.*/protocol_autogen/.*\.(h|hpp)$'
WarningsAsErrors: "*"

View File

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

View File

@@ -35,14 +35,13 @@ runs:
LOG_VERBOSITY: ${{ inputs.log_verbosity }}
SANITIZERS: ${{ inputs.sanitizers }}
run: |
echo 'Installing dependencies.'
conan install \
--profile ci \
--build="${BUILD_OPTION}" \
--options:host='&:tests=True' \
--options:host='&:xrpld=True' \
--settings:all build_type="${BUILD_TYPE}" \
--conf:all tools.build:jobs=${BUILD_NPROC} \
--conf:all tools.build:verbosity="${LOG_VERBOSITY}" \
--conf:all tools.compilation:verbosity="${LOG_VERBOSITY}" \
.
--profile:all ci \
--build="${BUILD_OPTION}" \
--options:host='&:tests=True' \
--options:host='&:xrpld=True' \
--settings:all build_type="${BUILD_TYPE}" \
--conf:all tools.build:jobs=${BUILD_NPROC} \
--conf:all tools.build:verbosity="${LOG_VERBOSITY}" \
--conf:all tools.compilation:verbosity="${LOG_VERBOSITY}" \
.

View File

@@ -15,7 +15,7 @@ runs:
shell: bash
env:
VERSION: ${{ github.ref_name }}
run: echo "VERSION=${VERSION}" >> "${GITHUB_ENV}"
run: echo "VERSION=${VERSION}" >>"${GITHUB_ENV}"
# When a tag is not pushed, then the version (e.g. 1.2.3-b0) is extracted
# from the BuildInfo.cpp file and the shortened commit hash appended to it.
@@ -28,17 +28,17 @@ runs:
echo 'Extracting version from BuildInfo.cpp.'
VERSION="$(cat src/libxrpl/protocol/BuildInfo.cpp | grep "versionString =" | awk -F '"' '{print $2}')"
if [[ -z "${VERSION}" ]]; then
echo 'Unable to extract version from BuildInfo.cpp.'
exit 1
echo 'Unable to extract version from BuildInfo.cpp.'
exit 1
fi
echo 'Appending shortened commit hash to version.'
SHA='${{ github.sha }}'
VERSION="${VERSION}+${SHA:0:7}"
echo "VERSION=${VERSION}" >> "${GITHUB_ENV}"
echo "VERSION=${VERSION}" >>"${GITHUB_ENV}"
- name: Output version
id: version
shell: bash
run: echo "version=${VERSION}" >> "${GITHUB_OUTPUT}"
run: echo "version=${VERSION}" >>"${GITHUB_OUTPUT}"

View File

@@ -0,0 +1,34 @@
name: Set compiler environment
description: "Set CC and CXX environment variables for the given compiler."
inputs:
compiler:
description: 'The compiler to use ("gcc" or "clang").'
required: true
runs:
using: composite
steps:
- name: Set CC and CXX for gcc
if: ${{ inputs.compiler == 'gcc' }}
shell: bash
run: |
echo "CC=gcc" >>"${GITHUB_ENV}"
echo "CXX=g++" >>"${GITHUB_ENV}"
- name: Set CC and CXX for clang
if: ${{ inputs.compiler == 'clang' }}
shell: bash
run: |
echo "CC=clang" >>"${GITHUB_ENV}"
echo "CXX=clang++" >>"${GITHUB_ENV}"
- name: Fail on unknown compiler
if: ${{ inputs.compiler != 'gcc' && inputs.compiler != 'clang' }}
shell: bash
env:
COMPILER: ${{ inputs.compiler }}
run: |
echo "Unknown compiler: $COMPILER" >&2
exit 1

View File

@@ -15,32 +15,35 @@ runs:
using: composite
steps:
- name: Set up Conan configuration
- name: Apply custom configuration to global.conf
shell: bash
run: |
echo 'Installing configuration.'
cat conan/global.conf ${{ runner.os == 'Linux' && '>>' || '>' }} $(conan config home)/global.conf
echo 'Conan configuration:'
conan config show '*'
- name: Set up Conan profile
- name: Show global configuration
shell: bash
run: |
conan config show '*'
- name: Install profiles
shell: bash
run: |
echo 'Installing profile.'
conan config install conan/profiles/ -tf $(conan config home)/profiles/
echo 'Conan profile:'
- name: Show CI profile
shell: bash
run: |
conan profile show --profile ci
- name: Set up Conan remote
- name: Add a remote
shell: bash
env:
REMOTE_NAME: ${{ inputs.remote_name }}
REMOTE_URL: ${{ inputs.remote_url }}
run: |
echo "Adding Conan remote '${REMOTE_NAME}' at '${REMOTE_URL}'."
conan remote add --index 0 --force "${REMOTE_NAME}" "${REMOTE_URL}"
echo 'Listing Conan remotes.'
- name: List remotes
shell: bash
run: |
conan remote list

View File

@@ -1,40 +1,12 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
day: monday
time: "04:00"
timezone: Etc/GMT
commit-message:
prefix: "ci: [DEPENDABOT] "
target-branch: develop
- package-ecosystem: github-actions
directory: .github/actions/build-deps/
schedule:
interval: weekly
day: monday
time: "04:00"
timezone: Etc/GMT
commit-message:
prefix: "ci: [DEPENDABOT] "
target-branch: develop
- package-ecosystem: github-actions
directory: .github/actions/generate-version/
schedule:
interval: weekly
day: monday
time: "04:00"
timezone: Etc/GMT
commit-message:
prefix: "ci: [DEPENDABOT] "
target-branch: develop
- package-ecosystem: github-actions
directory: .github/actions/setup-conan/
directories:
- /
- .github/actions/build-deps/
- .github/actions/generate-version/
- .github/actions/set-compiler-env/
- .github/actions/setup-conan/
schedule:
interval: weekly
day: monday

403
.github/scripts/format-inline-bash.py vendored Executable file
View File

@@ -0,0 +1,403 @@
#!/usr/bin/env python3
"""
Format embedded shell snippets using the shfmt hook configured in
.pre-commit-config.yaml.
Two shapes are recognised:
* YAML workflow/action files: literal block-scalar runs (`run: |`) and
single-line runs (`run: some command`). A single-line run is upgraded to
a `run: |` block scalar if shfmt's output spans multiple lines.
* Markdown files: ``` ```bash ``` fenced code blocks.
Any block that shfmt cannot parse is skipped with a warning on stderr, so
the file is left untouched and surrounding blocks still get formatted.
For each occurrence the body is dedented, written to a temp .sh file,
formatted via `pre-commit run shfmt --files <temp>` (falling back to
`prek`), then re-indented and written back in place.
When invoked without arguments, every .yml/.yaml under .github/ plus every
.md file in the repo is scanned. When invoked with file arguments (the
pre-commit case), only those files are processed.
"""
from __future__ import annotations
import re
import shutil
import subprocess
import sys
import tempfile
from dataclasses import dataclass
from pathlib import Path
from typing import Union
REPO = Path(__file__).resolve().parents[2]
_HOOK_RUNNER = next((cmd for cmd in ("pre-commit", "prek") if shutil.which(cmd)), None)
if _HOOK_RUNNER is None:
sys.exit("error: neither `pre-commit` nor `prek` found on PATH")
RUN_BLOCK_RE = re.compile(r"^(?P<prefix>[ \t]*(?:- )?)run:[ \t]*\|[+-]?[ \t]*$")
RUN_INLINE_RE = re.compile(
r"^(?P<prefix>[ \t]*(?:- )?)run:[ \t]+" r"(?P<value>(?!\|[+-]?[ \t]*$)\S.*?)[ \t]*$"
)
MD_BASH_OPEN_RE = re.compile(r"^(?P<indent>[ ]{0,3})`{3}bash[ \t]*$")
MD_FENCE_CLOSE_RE = re.compile(r"^[ ]{0,3}`{3,}[ \t]*$")
@dataclass(frozen=True)
class BlockRun:
"""A `run: |` block scalar; `body_start:body_end` slices into `lines`."""
body_start: int
body_end: int
body_indent: int
@dataclass(frozen=True)
class InlineRun:
"""A single-line `run: value` at `line_idx`."""
line_idx: int
prefix: str
value: str
@dataclass(frozen=True)
class MdBashBlock:
"""A markdown ``` ```bash ``` fenced code block.
`body_start:body_end` slices into the file's lines; `open_line_idx`
points at the opening fence line.
"""
open_line_idx: int
body_start: int
body_end: int
body_indent: int
RunItem = Union[BlockRun, InlineRun]
def _scan_block_body(
lines: list[str], body_start: int, run_col: int
) -> tuple[int | None, int]:
"""Locate the body of a `run: |` block scalar starting at `body_start`.
Returns `(body_indent, scan_end)`. `scan_end` is the line index where the
outer scanner should resume. `body_indent` is `None` when no body is
present (the scalar is empty, or the next non-blank line has indent
`<= run_col`).
"""
body_indent: int | None = None
scan_end = len(lines)
for idx in range(body_start, len(lines)):
line = lines[idx]
if line.strip() == "":
continue
indent = len(line) - len(line.lstrip(" "))
if body_indent is None:
if indent > run_col:
body_indent = indent
else:
scan_end = idx
break
elif indent < body_indent:
scan_end = idx
break
if body_indent is not None:
while scan_end > body_start and lines[scan_end - 1].strip() == "":
scan_end -= 1
if scan_end <= body_start:
body_indent = None
return body_indent, scan_end
def find_run_blocks(lines: list[str]) -> list[RunItem]:
"""Return run items in document order."""
items: list[RunItem] = []
line_idx = 0
while line_idx < len(lines):
line = lines[line_idx]
if block_match := RUN_BLOCK_RE.match(line):
run_col = len(block_match.group("prefix"))
body_start = line_idx + 1
body_indent, scan_end = _scan_block_body(lines, body_start, run_col)
if body_indent is not None:
items.append(
BlockRun(
body_start=body_start,
body_end=scan_end,
body_indent=body_indent,
)
)
line_idx = scan_end
continue
if inline_match := RUN_INLINE_RE.match(line):
items.append(
InlineRun(
line_idx=line_idx,
prefix=inline_match.group("prefix"),
value=inline_match.group("value"),
)
)
line_idx += 1
return items
def find_md_bash_blocks(lines: list[str]) -> list[MdBashBlock]:
"""Return ``` ```bash ``` fenced code blocks in document order."""
blocks: list[MdBashBlock] = []
line_idx = 0
while line_idx < len(lines):
open_match = MD_BASH_OPEN_RE.match(lines[line_idx])
if not open_match:
line_idx += 1
continue
body_start = line_idx + 1
close_idx = next(
(
j
for j in range(body_start, len(lines))
if MD_FENCE_CLOSE_RE.match(lines[j])
),
None,
)
if close_idx is None:
line_idx = body_start
continue
body = lines[body_start:close_idx]
non_blank = [b for b in body if b.strip()]
body_indent = (
min(len(b) - len(b.lstrip(" ")) for b in non_blank)
if non_blank
else len(open_match.group("indent"))
)
blocks.append(
MdBashBlock(
open_line_idx=line_idx,
body_start=body_start,
body_end=close_idx,
body_indent=body_indent,
)
)
line_idx = close_idx + 1
return blocks
def dedent(lines: list[str], n: int) -> list[str]:
pad = " " * n
return [
(
""
if line.strip() == ""
else (line[n:] if line.startswith(pad) else line.lstrip(" "))
)
for line in lines
]
def reindent(lines: list[str], n: int) -> list[str]:
pad = " " * n
return [pad + line if line else "" for line in lines]
_SHFMT_ERR_RE = re.compile(r"\.sh:\d+:\d+:\s")
_GHA_EXPR_RE = re.compile(r"\$\{\{.*?\}\}", re.DOTALL)
_GHA_PLACEHOLDER_RE = re.compile(r"__GHA_EXPR_(\d+)__")
def _encode_gha_exprs(text: str) -> tuple[str, list[str]]:
"""Replace `${{ ... }}` expressions with bash-safe placeholder identifiers."""
exprs: list[str] = []
def repl(match: re.Match[str]) -> str:
exprs.append(match.group(0))
return f"__GHA_EXPR_{len(exprs) - 1}__"
return _GHA_EXPR_RE.sub(repl, text), exprs
def _decode_gha_exprs(text: str, exprs: list[str]) -> str:
"""Restore `${{ ... }}` expressions from placeholder identifiers."""
return _GHA_PLACEHOLDER_RE.sub(lambda m: exprs[int(m.group(1))], text)
def shfmt_via_hook(tmp_path: Path) -> tuple[bool, str]:
# `${{ ... }}` is not valid shell, so swap it for a placeholder identifier
# that shfmt can parse, then restore it after formatting.
encoded, exprs = _encode_gha_exprs(tmp_path.read_text())
if exprs:
tmp_path.write_text(encoded)
res = subprocess.run(
[_HOOK_RUNNER, "run", "shfmt", "--files", str(tmp_path)],
cwd=REPO,
capture_output=True,
text=True,
)
output = res.stdout + res.stderr
# shfmt emits parse errors as "<path>:<line>:<col>: <message>".
parse_err = bool(_SHFMT_ERR_RE.search(output))
# A non-zero exit that is neither a parse error nor pre-commit's "I had
# to modify files" signal means the hook itself failed to run (missing
# binary, install failure, bad config, ...). Surface that loudly rather
# than silently treating it as a no-op.
if (
res.returncode != 0
and not parse_err
and "files were modified by this hook" not in output
):
sys.exit(
f"error: `{_HOOK_RUNNER} run shfmt` failed with exit {res.returncode}:\n{output}"
)
if exprs and not parse_err:
tmp_path.write_text(_decode_gha_exprs(tmp_path.read_text(), exprs))
return not parse_err, output
def _skip(path: Path, where: int, kind: str, output: str) -> None:
print(
f" shfmt could not parse {kind} at {path}:{where + 1} — skipped",
file=sys.stderr,
)
print(f" {output.strip()}", file=sys.stderr)
def process_yaml_file(path: Path, tmp_path: Path) -> int:
text = path.read_text()
had_nl = text.endswith("\n")
lines = text.split("\n")
if had_nl:
lines = lines[:-1]
items = find_run_blocks(lines)
if not items:
return 0
changed = 0
# Process in reverse so earlier indices remain valid as we splice.
for item in reversed(items):
if isinstance(item, BlockRun):
body = lines[item.body_start : item.body_end]
tmp_path.write_text("\n".join(dedent(body, item.body_indent)) + "\n")
ok, output = shfmt_via_hook(tmp_path)
if not ok:
_skip(path, item.body_start, "block", output)
continue
formatted = tmp_path.read_text().rstrip("\n")
new_body = reindent(formatted.split("\n"), item.body_indent)
if new_body != body:
lines[item.body_start : item.body_end] = new_body
changed += 1
else:
tmp_path.write_text(item.value + "\n")
ok, output = shfmt_via_hook(tmp_path)
if not ok:
_skip(path, item.line_idx, "inline run", output)
continue
formatted = tmp_path.read_text().rstrip("\n")
if formatted == item.value:
continue
formatted_lines = formatted.split("\n")
if len(formatted_lines) == 1:
lines[item.line_idx] = f"{item.prefix}run: {formatted}"
else:
body_indent = len(item.prefix) + 2
lines[item.line_idx : item.line_idx + 1] = [
f"{item.prefix}run: |",
*reindent(formatted_lines, body_indent),
]
changed += 1
new_text = "\n".join(lines) + ("\n" if had_nl else "")
if new_text != text:
path.write_text(new_text)
return changed
def process_md_file(path: Path, tmp_path: Path) -> int:
text = path.read_text()
had_nl = text.endswith("\n")
lines = text.split("\n")
if had_nl:
lines = lines[:-1]
blocks = find_md_bash_blocks(lines)
if not blocks:
return 0
changed = 0
for block in reversed(blocks):
body = lines[block.body_start : block.body_end]
tmp_path.write_text("\n".join(dedent(body, block.body_indent)) + "\n")
ok, output = shfmt_via_hook(tmp_path)
if not ok:
_skip(path, block.open_line_idx, "```bash block", output)
continue
formatted = tmp_path.read_text().rstrip("\n")
formatted_lines = formatted.split("\n") if formatted else []
new_body = reindent(formatted_lines, block.body_indent)
if new_body != body:
lines[block.body_start : block.body_end] = new_body
changed += 1
new_text = "\n".join(lines) + ("\n" if had_nl else "")
if new_text != text:
path.write_text(new_text)
return changed
def process_file(path: Path, tmp_path: Path) -> int:
if path.suffix in (".yml", ".yaml"):
return process_yaml_file(path, tmp_path)
if path.suffix == ".md":
return process_md_file(path, tmp_path)
return 0
def gather_files(argv: list[str]) -> list[Path]:
"""Return YAML workflow/action files and markdown files that we should
process — either the paths in `argv` or, when `argv` is empty, every
such file in the repo (skipping `external/`)."""
if argv:
candidates: list[Path] = [
(REPO / a).resolve() if not Path(a).is_absolute() else Path(a) for a in argv
]
else:
gh = REPO / ".github"
candidates = [
*gh.rglob("*.yml"),
*gh.rglob("*.yaml"),
*(
p
for p in REPO.rglob("*.md")
if "external" not in p.relative_to(REPO).parts
),
]
return sorted(
p
for p in candidates
if p.exists()
and (
(p.suffix in (".yml", ".yaml") and ".github" in p.parts)
or p.suffix == ".md"
)
)
def main(argv: list[str]) -> int:
files = gather_files(argv)
if not files:
return 0
with tempfile.TemporaryDirectory(prefix="format-inline-bash-") as tmpdir:
tmp_path = Path(tmpdir) / "shfmt.sh"
total = 0
for f in files:
n = process_file(f, tmp_path)
if n:
print(f"{f.relative_to(REPO)}: reformatted {n} block(s)")
total += n
return 1 if total else 0
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))

0
.github/scripts/levelization/generate.py vendored Normal file → Executable file
View File

View File

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

View File

@@ -6,7 +6,7 @@ set -e
# On MacOS, ensure that GNU sed is installed and available as `gsed`.
SED_COMMAND=sed
if [[ "${OSTYPE}" == 'darwin'* ]]; then
if ! command -v gsed &> /dev/null; then
if ! command -v gsed &>/dev/null; then
echo "Error: gsed is not installed. Please install it using 'brew install gnu-sed'."
exit 1
fi

View File

@@ -8,12 +8,12 @@ set -e
SED_COMMAND=sed
HEAD_COMMAND=head
if [[ "${OSTYPE}" == 'darwin'* ]]; then
if ! command -v gsed &> /dev/null; then
if ! command -v gsed &>/dev/null; then
echo "Error: gsed is not installed. Please install it using 'brew install gnu-sed'."
exit 1
fi
SED_COMMAND=gsed
if ! command -v ghead &> /dev/null; then
if ! command -v ghead &>/dev/null; then
echo "Error: ghead is not installed. Please install it using 'brew install coreutils'."
exit 1
fi
@@ -43,9 +43,6 @@ pushd "${DIRECTORY}"
# Rename the files.
find cmake -type f -name 'Rippled*.cmake' -exec bash -c 'mv "${1}" "${1/Rippled/Xrpl}"' - {} \;
find cmake -type f -name 'Ripple*.cmake' -exec bash -c 'mv "${1}" "${1/Ripple/Xrpl}"' - {} \;
if [ -e cmake/xrpl_add_test.cmake ]; then
mv cmake/xrpl_add_test.cmake cmake/XrplAddTest.cmake
fi
if [ -e include/xrpl/proto/ripple.proto ]; then
mv include/xrpl/proto/ripple.proto include/xrpl/proto/xrpl.proto
fi
@@ -60,7 +57,6 @@ find cmake -type f -name '*.cmake' | while read -r FILE; do
done
${SED_COMMAND} -i -E 's/Rippled?/Xrpl/g' CMakeLists.txt
${SED_COMMAND} -i 's/ripple/xrpl/g' CMakeLists.txt
${SED_COMMAND} -i 's/include(xrpl_add_test)/include(XrplAddTest)/' src/tests/libxrpl/CMakeLists.txt
${SED_COMMAND} -i 's/ripple.pb.h/xrpl.pb.h/' include/xrpl/protocol/messages.h
${SED_COMMAND} -i 's/ripple.pb.h/xrpl.pb.h/' BUILD.md
${SED_COMMAND} -i 's/ripple.pb.h/xrpl.pb.h/' BUILD.md
@@ -74,10 +70,10 @@ if grep -q '"xrpld"' cmake/XrplCore.cmake; then
# The script has been rerun, so just restore the name of the binary.
${SED_COMMAND} -i 's/"xrpld"/"rippled"/' cmake/XrplCore.cmake
elif ! grep -q '"rippled"' cmake/XrplCore.cmake; then
${HEAD_COMMAND} -n -1 cmake/XrplCore.cmake > cmake.tmp
echo ' # For the time being, we will keep the name of the binary as it was.' >> cmake.tmp
echo ' set_target_properties(xrpld PROPERTIES OUTPUT_NAME "rippled")' >> cmake.tmp
tail -1 cmake/XrplCore.cmake >> cmake.tmp
${HEAD_COMMAND} -n -1 cmake/XrplCore.cmake >cmake.tmp
echo ' # For the time being, we will keep the name of the binary as it was.' >>cmake.tmp
echo ' set_target_properties(xrpld PROPERTIES OUTPUT_NAME "rippled")' >>cmake.tmp
tail -1 cmake/XrplCore.cmake >>cmake.tmp
mv cmake.tmp cmake/XrplCore.cmake
fi

View File

@@ -6,7 +6,7 @@ set -e
# On MacOS, ensure that GNU sed is installed and available as `gsed`.
SED_COMMAND=sed
if [[ "${OSTYPE}" == 'darwin'* ]]; then
if ! command -v gsed &> /dev/null; then
if ! command -v gsed &>/dev/null; then
echo "Error: gsed is not installed. Please install it using 'brew install gnu-sed'."
exit 1
fi

View File

@@ -6,7 +6,7 @@ set -e
# On MacOS, ensure that GNU sed is installed and available as `gsed`.
SED_COMMAND=sed
if [[ "${OSTYPE}" == 'darwin'* ]]; then
if ! command -v gsed &> /dev/null; then
if ! command -v gsed &>/dev/null; then
echo "Error: gsed is not installed. Please install it using 'brew install gnu-sed'."
exit 1
fi
@@ -62,37 +62,37 @@ done
# restoring the verbiage that is already present in LICENSE.md. Ensure that if
# the script is run multiple times, duplicate notices are not added.
if ! grep -q 'Raw Material Software' include/xrpl/beast/core/CurrentThreadName.h; then
echo -e "// Portions of this file are from JUCE (http://www.juce.com).\n// Copyright (c) 2013 - Raw Material Software Ltd.\n// Please visit http://www.juce.com\n\n$(cat include/xrpl/beast/core/CurrentThreadName.h)" > include/xrpl/beast/core/CurrentThreadName.h
echo -e "// Portions of this file are from JUCE (http://www.juce.com).\n// Copyright (c) 2013 - Raw Material Software Ltd.\n// Please visit http://www.juce.com\n\n$(cat include/xrpl/beast/core/CurrentThreadName.h)" >include/xrpl/beast/core/CurrentThreadName.h
fi
if ! grep -q 'Dev Null' src/test/app/NetworkID_test.cpp; then
echo -e "// Copyright (c) 2020 Dev Null Productions\n\n$(cat src/test/app/NetworkID_test.cpp)" > src/test/app/NetworkID_test.cpp
echo -e "// Copyright (c) 2020 Dev Null Productions\n\n$(cat src/test/app/NetworkID_test.cpp)" >src/test/app/NetworkID_test.cpp
fi
if ! grep -q 'Dev Null' src/test/app/tx/apply_test.cpp; then
echo -e "// Copyright (c) 2020 Dev Null Productions\n\n$(cat src/test/app/tx/apply_test.cpp)" > src/test/app/tx/apply_test.cpp
echo -e "// Copyright (c) 2020 Dev Null Productions\n\n$(cat src/test/app/tx/apply_test.cpp)" >src/test/app/tx/apply_test.cpp
fi
if ! grep -q 'Dev Null' src/test/rpc/ManifestRPC_test.cpp; then
echo -e "// Copyright (c) 2020 Dev Null Productions\n\n$(cat src/test/rpc/ManifestRPC_test.cpp)" > src/test/rpc/ManifestRPC_test.cpp
echo -e "// Copyright (c) 2020 Dev Null Productions\n\n$(cat src/test/rpc/ManifestRPC_test.cpp)" >src/test/rpc/ManifestRPC_test.cpp
fi
if ! grep -q 'Dev Null' src/test/rpc/ValidatorInfo_test.cpp; then
echo -e "// Copyright (c) 2020 Dev Null Productions\n\n$(cat src/test/rpc/ValidatorInfo_test.cpp)" > src/test/rpc/ValidatorInfo_test.cpp
echo -e "// Copyright (c) 2020 Dev Null Productions\n\n$(cat src/test/rpc/ValidatorInfo_test.cpp)" >src/test/rpc/ValidatorInfo_test.cpp
fi
if ! grep -q 'Dev Null' src/xrpld/rpc/handlers/server_info/Manifest.cpp; then
echo -e "// Copyright (c) 2019 Dev Null Productions\n\n$(cat src/xrpld/rpc/handlers/server_info/Manifest.cpp)" > src/xrpld/rpc/handlers/server_info/Manifest.cpp
echo -e "// Copyright (c) 2019 Dev Null Productions\n\n$(cat src/xrpld/rpc/handlers/server_info/Manifest.cpp)" >src/xrpld/rpc/handlers/server_info/Manifest.cpp
fi
if ! grep -q 'Dev Null' src/xrpld/rpc/handlers/admin/status/ValidatorInfo.cpp; then
echo -e "// Copyright (c) 2019 Dev Null Productions\n\n$(cat src/xrpld/rpc/handlers/admin/status/ValidatorInfo.cpp)" > src/xrpld/rpc/handlers/admin/status/ValidatorInfo.cpp
echo -e "// Copyright (c) 2019 Dev Null Productions\n\n$(cat src/xrpld/rpc/handlers/admin/status/ValidatorInfo.cpp)" >src/xrpld/rpc/handlers/admin/status/ValidatorInfo.cpp
fi
if ! grep -q 'Bougalis' include/xrpl/basics/SlabAllocator.h; then
echo -e "// Copyright (c) 2022, Nikolaos D. Bougalis <nikb@bougalis.net>\n\n$(cat include/xrpl/basics/SlabAllocator.h)" > include/xrpl/basics/SlabAllocator.h # cspell: ignore Nikolaos Bougalis nikb
echo -e "// Copyright (c) 2022, Nikolaos D. Bougalis <nikb@bougalis.net>\n\n$(cat include/xrpl/basics/SlabAllocator.h)" >include/xrpl/basics/SlabAllocator.h # cspell: ignore Nikolaos Bougalis nikb
fi
if ! grep -q 'Bougalis' include/xrpl/basics/spinlock.h; then
echo -e "// Copyright (c) 2022, Nikolaos D. Bougalis <nikb@bougalis.net>\n\n$(cat include/xrpl/basics/spinlock.h)" > include/xrpl/basics/spinlock.h # cspell: ignore Nikolaos Bougalis nikb
echo -e "// Copyright (c) 2022, Nikolaos D. Bougalis <nikb@bougalis.net>\n\n$(cat include/xrpl/basics/spinlock.h)" >include/xrpl/basics/spinlock.h # cspell: ignore Nikolaos Bougalis nikb
fi
if ! grep -q 'Bougalis' include/xrpl/basics/tagged_integer.h; then
echo -e "// Copyright (c) 2014, Nikolaos D. Bougalis <nikb@bougalis.net>\n\n$(cat include/xrpl/basics/tagged_integer.h)" > include/xrpl/basics/tagged_integer.h # cspell: ignore Nikolaos Bougalis nikb
echo -e "// Copyright (c) 2014, Nikolaos D. Bougalis <nikb@bougalis.net>\n\n$(cat include/xrpl/basics/tagged_integer.h)" >include/xrpl/basics/tagged_integer.h # cspell: ignore Nikolaos Bougalis nikb
fi
if ! grep -q 'Ritchford' include/xrpl/beast/utility/Zero.h; then
echo -e "// Copyright (c) 2014, Tom Ritchford <tom@swirly.com>\n\n$(cat include/xrpl/beast/utility/Zero.h)" > include/xrpl/beast/utility/Zero.h # cspell: ignore Ritchford
echo -e "// Copyright (c) 2014, Tom Ritchford <tom@swirly.com>\n\n$(cat include/xrpl/beast/utility/Zero.h)" >include/xrpl/beast/utility/Zero.h # cspell: ignore Ritchford
fi
# Restore newlines and tabs in string literals in the affected file.

View File

@@ -6,7 +6,7 @@ set -e
# On MacOS, ensure that GNU sed is installed and available as `gsed`.
SED_COMMAND=sed
if [[ "${OSTYPE}" == 'darwin'* ]]; then
if ! command -v gsed &> /dev/null; then
if ! command -v gsed &>/dev/null; then
echo "Error: gsed is not installed. Please install it using 'brew install gnu-sed'."
exit 1
fi

View File

@@ -6,7 +6,7 @@ set -e
# On MacOS, ensure that GNU sed is installed and available as `gsed`.
SED_COMMAND=sed
if [[ "${OSTYPE}" == 'darwin'* ]]; then
if ! command -v gsed &> /dev/null; then
if ! command -v gsed &>/dev/null; then
echo "Error: gsed is not installed. Please install it using 'brew install gnu-sed'."
exit 1
fi

View File

@@ -6,7 +6,7 @@ set -e
# On MacOS, ensure that GNU sed is installed and available as `gsed`.
SED_COMMAND=sed
if [[ "${OSTYPE}" == 'darwin'* ]]; then
if ! command -v gsed &> /dev/null; then
if ! command -v gsed &>/dev/null; then
echo "Error: gsed is not installed. Please install it using 'brew install gnu-sed'."
exit 1
fi

View File

@@ -1,384 +1,281 @@
#!/usr/bin/env python3
import argparse
import dataclasses
import itertools
import json
from dataclasses import dataclass
from pathlib import Path
THIS_DIR = Path(__file__).parent.resolve()
_BASE_CMAKE_ARGS = ["-Dtests=ON", "-Dwerr=ON", "-Dxrpld=ON", "-Dwextra=ON"]
@dataclass
class Config:
architecture: list[dict]
os: list[dict]
# Maps sanitizer names (as used in cmake) to short config-name suffixes.
_SANITIZER_SUFFIX: dict[str, str] = {
"address": "asan",
"undefinedbehavior": "ubsan",
"thread": "tsan",
}
def get_cmake_args(build_type: str, extra_args: str) -> str:
"""Get the full list of CMake arguments for a config."""
args = _BASE_CMAKE_ARGS.copy()
if build_type == "Release":
args.append("-Dassert=ON")
if extra_args:
args.extend(extra_args.split())
return " ".join(args)
# ---------------------------------------------------------------------------
# Input types — shapes of the JSON config files
# ---------------------------------------------------------------------------
@dataclasses.dataclass
class LinuxConfig:
"""One entry in linux.json's 'configs' or 'package_configs' arrays."""
compiler: list[str]
build_type: list[str]
cmake_args: list[str]
arch: list[str]
sanitizers: list[str] = dataclasses.field(default_factory=list)
suffix: str = ""
extra_cmake_args: str = ""
image: str = "" # only used by package_configs entries
"""
Generate a strategy matrix for GitHub Actions CI.
@dataclasses.dataclass
class LinuxFile:
"""Shape of linux.json."""
On each PR commit we will build a selection of Debian, RHEL, Ubuntu, MacOS, and
Windows configurations, while upon merge into the develop or release branches,
we will build all configurations, and test most of them.
image_tag: str
configs: dict[str, list[LinuxConfig]] # distro → configs
package_configs: dict[str, list[LinuxConfig]] # distro → packaging configs
We will further set additional CMake arguments as follows:
- All builds will have the `tests`, `werr`, and `xrpld` options.
- All builds will have the `wextra` option except for GCC 12 and Clang 16.
- All release builds will have the `assert` option.
- Certain Debian Bookworm configurations will change the reference fee, enable
codecov, and enable voidstar in PRs.
"""
@classmethod
def load(cls, path: Path) -> "LinuxFile":
data = json.loads(path.read_text())
def parse(section: dict) -> dict[str, list[LinuxConfig]]:
return {
distro: [LinuxConfig(**c) for c in cfgs]
for distro, cfgs in section.items()
}
return cls(
image_tag=data["image_tag"],
configs=parse(data["configs"]),
package_configs=parse(data.get("package_configs", {})),
)
def build_config_name(os_entry: dict[str, str], platform: str, build_type: str) -> str:
parts = [os_entry["distro_name"]]
for key in ("distro_version", "compiler_name", "compiler_version"):
if value := os_entry[key]:
parts.append(value)
parts.append("arm64" if "arm64" in platform else "amd64")
parts.append(build_type.lower())
return "-".join(parts)
@dataclasses.dataclass
class PlatformConfig:
"""One entry in macos.json's or windows.json's 'configs' array."""
build_type: list[str]
build_only: bool = False # if true, skip tests (e.g. macos/Windows Debug)
extra_cmake_args: str = ""
def __post_init__(self) -> None:
if isinstance(self.build_type, str):
self.build_type = [self.build_type]
def generate_packaging_matrix(config: Config) -> list[dict]:
"""Emit one entry per os entry with `package: true`. Architecture is
hardcoded to linux/amd64 here (and the runner is hardcoded at the
workflow level) until arm64 packaging is ready.
@dataclasses.dataclass
class PlatformFile:
"""Shape of macos.json and windows.json."""
platform: str # e.g. "macos/arm64" or "windows/amd64"
runner: list[str] # GitHub Actions runner labels
configs: list[PlatformConfig]
@classmethod
def load(cls, path: Path) -> "PlatformFile":
data = json.loads(path.read_text())
return cls(
platform=data["platform"],
runner=data["runner"],
configs=[PlatformConfig(**c) for c in data["configs"]],
)
# ---------------------------------------------------------------------------
# Output types — shapes of the generated GitHub Actions matrix entries
# ---------------------------------------------------------------------------
@dataclasses.dataclass
class Architecture:
platform: str
runner: list[str]
@dataclasses.dataclass
class MatrixEntry:
"""One entry in the generated build/test strategy matrix."""
config_name: str
cmake_args: str
cmake_target: str
build_only: bool
build_type: str
architecture: Architecture
sanitizers: str
image: str = "" # container image; empty for macOS/Windows (runs natively)
compiler: str = "" # compiler name ("gcc" or "clang"); empty for macOS/Windows
@dataclasses.dataclass
class PackagingEntry:
"""One entry in the generated packaging strategy matrix."""
artifact_name: str
image: str
distro: str # e.g. "debian" or "rhel"; drives package-format-specific steps
# ---------------------------------------------------------------------------
# Matrix expansion
# ---------------------------------------------------------------------------
_ARCHS: dict[str, Architecture] = {
"amd64": Architecture(
platform="linux/amd64", runner=["self-hosted", "Linux", "X64", "heavy"]
),
"arm64": Architecture(
platform="linux/arm64",
runner=["self-hosted", "Linux", "ARM64", "heavy-arm64"],
),
}
def expand_linux_matrix(linux: LinuxFile) -> list[MatrixEntry]:
"""Expand a LinuxFile into a flat list of matrix entries.
Each config entry is expanded over the cross-product of its
compiler, build_type, sanitizers, and architecture lists.
"""
return [
{
"artifact_name": f"xrpld-{build_config_name(os, 'linux/amd64', 'Release')}",
"os": os,
}
for os in config.os
if os.get("package", False)
]
entries: list[MatrixEntry] = []
for distro, configs in linux.configs.items():
for cfg in configs:
# An empty sanitizers list means "one entry with no sanitizer".
effective_sanitizers = cfg.sanitizers or [""]
effective_archs = {arch: _ARCHS[arch] for arch in cfg.arch}
def generate_strategy_matrix(all: bool, config: Config) -> list[dict]:
configurations = []
for architecture, os, build_type, cmake_args in itertools.product(
config.architecture, config.os, config.build_type, config.cmake_args
):
# The default CMake target is 'all' for Linux and MacOS and 'install'
# for Windows, but it can get overridden for certain configurations.
cmake_target = "install" if os["distro_name"] == "windows" else "all"
# We build and test all configurations by default, except for Windows in
# Debug, because it is too slow, as well as when code coverage is
# enabled as that mode already runs the tests.
build_only = False
if os["distro_name"] == "windows" and build_type == "Debug":
build_only = True
# Only generate a subset of configurations in PRs.
if not all:
# Debian:
# - Bookworm using GCC 13: Debug on linux/amd64, set the reference
# fee to 500 and enable code coverage (which will be done below).
# - Bookworm using GCC 15: Debug on linux/amd64, enable Address and
# UB sanitizers (which will be done below).
# - Bookworm using Clang 16: Debug on linux/amd64, enable voidstar.
# - Bookworm using Clang 17: Release on linux/amd64, set the
# reference fee to 1000.
# - Bookworm using Clang 20: Debug on linux/amd64, enable Address
# and UB sanitizers (which will be done below).
if os["distro_name"] == "debian":
skip = True
if os["distro_version"] == "bookworm":
if (
f"{os['compiler_name']}-{os['compiler_version']}" == "gcc-13"
and build_type == "Debug"
and architecture["platform"] == "linux/amd64"
):
cmake_args = f"-DUNIT_TEST_REFERENCE_FEE=500 {cmake_args}"
skip = False
if (
f"{os['compiler_name']}-{os['compiler_version']}" == "gcc-15"
and build_type == "Release"
and architecture["platform"] == "linux/amd64"
):
skip = False
if (
f"{os['compiler_name']}-{os['compiler_version']}" == "clang-16"
and build_type == "Debug"
and architecture["platform"] == "linux/amd64"
):
cmake_args = f"-Dvoidstar=ON {cmake_args}"
skip = False
if (
f"{os['compiler_name']}-{os['compiler_version']}" == "clang-17"
and build_type == "Release"
and architecture["platform"] == "linux/amd64"
):
cmake_args = f"-DUNIT_TEST_REFERENCE_FEE=1000 {cmake_args}"
skip = False
elif os["distro_version"] == "trixie":
if (
f"{os['compiler_name']}-{os['compiler_version']}" == "clang-22"
and build_type == "Debug"
and architecture["platform"] == "linux/amd64"
):
skip = False
if skip:
continue
# RHEL:
# - 9 using GCC 12: Debug and Release on linux/amd64
# (Release is required for RPM packaging).
# - 10 using Clang: Release on linux/amd64.
if os["distro_name"] == "rhel":
skip = True
if os["distro_version"] == "9":
if (
f"{os['compiler_name']}-{os['compiler_version']}" == "gcc-12"
and build_type in ["Debug", "Release"]
and architecture["platform"] == "linux/amd64"
):
skip = False
elif os["distro_version"] == "10":
if (
f"{os['compiler_name']}-{os['compiler_version']}" == "clang-any"
and build_type == "Release"
and architecture["platform"] == "linux/amd64"
):
skip = False
if skip:
continue
# Ubuntu:
# - Jammy using GCC 12: Debug on linux/arm64, Release on
# linux/amd64 (Release is required for DEB packaging).
# - Noble using GCC 14: Release on linux/amd64.
# - Noble using Clang 18: Debug on linux/amd64.
# - Noble using Clang 19: Release on linux/arm64.
if os["distro_name"] == "ubuntu":
skip = True
if os["distro_version"] == "jammy":
if (
f"{os['compiler_name']}-{os['compiler_version']}" == "gcc-12"
and build_type == "Debug"
and architecture["platform"] == "linux/arm64"
):
skip = False
if (
f"{os['compiler_name']}-{os['compiler_version']}" == "gcc-12"
and build_type == "Release"
and architecture["platform"] == "linux/amd64"
):
skip = False
elif os["distro_version"] == "noble":
if (
f"{os['compiler_name']}-{os['compiler_version']}" == "gcc-14"
and build_type == "Release"
and architecture["platform"] == "linux/amd64"
):
skip = False
if (
f"{os['compiler_name']}-{os['compiler_version']}" == "clang-18"
and build_type == "Debug"
and architecture["platform"] == "linux/amd64"
):
skip = False
if (
f"{os['compiler_name']}-{os['compiler_version']}" == "clang-19"
and build_type == "Release"
and architecture["platform"] == "linux/arm64"
):
skip = False
if skip:
continue
# MacOS:
# - Debug on macos/arm64.
if os["distro_name"] == "macos" and not (
build_type == "Debug" and architecture["platform"] == "macos/arm64"
for compiler, build_type, sanitizer, (arch, arch_info) in itertools.product(
cfg.compiler,
cfg.build_type,
effective_sanitizers,
effective_archs.items(),
):
continue
name = f"{distro}-{compiler}-{build_type.lower()}-{arch}"
suffix_parts = [
s for s in [cfg.suffix, _SANITIZER_SUFFIX.get(sanitizer, "")] if s
]
if suffix_parts:
name += "-" + "-".join(suffix_parts)
# Windows:
# - Release on windows/amd64.
if os["distro_name"] == "windows" and not (
build_type == "Release" and architecture["platform"] == "windows/amd64"
):
continue
# Additional CMake arguments.
cmake_args = f"{cmake_args} -Dtests=ON -Dwerr=ON -Dxrpld=ON"
if not f"{os['compiler_name']}-{os['compiler_version']}" in [
"gcc-12",
"clang-16",
]:
cmake_args = f"{cmake_args} -Dwextra=ON"
if build_type == "Release":
cmake_args = f"{cmake_args} -Dassert=ON"
# We skip all RHEL on arm64 due to a build failure that needs further
# investigation.
if os["distro_name"] == "rhel" and architecture["platform"] == "linux/arm64":
continue
# We skip all clang 20+ on arm64 due to Boost build error.
if (
os["compiler_name"] == "clang"
and os["compiler_version"].isdigit()
and int(os["compiler_version"]) >= 20
and architecture["platform"] == "linux/arm64"
):
continue
# Enable code coverage for Debian Bookworm using GCC 13 in Debug on
# linux/amd64.
if (
f"{os['distro_name']}-{os['distro_version']}" == "debian-bookworm"
and f"{os['compiler_name']}-{os['compiler_version']}" == "gcc-13"
and build_type == "Debug"
and architecture["platform"] == "linux/amd64"
):
cmake_args = f"{cmake_args} -Dcoverage=ON -Dcoverage_format=xml -DCODE_COVERAGE_VERBOSE=ON -DCMAKE_C_FLAGS=-O0 -DCMAKE_CXX_FLAGS=-O0"
# Enable unity build for Ubuntu Jammy using GCC 12 in Debug on
# linux/amd64.
if (
f"{os['distro_name']}-{os['distro_version']}" == "ubuntu-jammy"
and f"{os['compiler_name']}-{os['compiler_version']}" == "gcc-12"
and build_type == "Debug"
and architecture["platform"] == "linux/amd64"
):
cmake_args = f"{cmake_args} -Dunity=ON"
# Generate a unique name for the configuration, e.g. macos-arm64-debug
# or debian-bookworm-gcc-12-amd64-release.
config_name = build_config_name(os, architecture["platform"], build_type)
if "-Dcoverage=ON" in cmake_args:
config_name += "-coverage"
if "-Dunity=ON" in cmake_args:
config_name += "-unity"
# Add the configuration to the list, with the most unique fields first,
# so that they are easier to identify in the GitHub Actions UI, as long
# names get truncated.
# Add Address and UB sanitizers as separate configurations for specific
# bookworm distros. Thread sanitizer is currently disabled (see below).
# GCC-Asan xrpld-embedded tests are failing because of https://github.com/google/sanitizers/issues/856
if (
os["distro_version"] == "bookworm"
and f"{os['compiler_name']}-{os['compiler_version']}" == "gcc-15"
) or (
os["distro_version"] == "trixie"
and f"{os['compiler_name']}-{os['compiler_version']}" == "clang-22"
):
# Add ASAN and UBSAN configurations for both gcc-15 and clang-22
configurations.append(
{
"config_name": config_name + "-asan",
"cmake_args": cmake_args,
"cmake_target": cmake_target,
"build_only": build_only,
"build_type": build_type,
"os": os,
"architecture": architecture,
"sanitizers": "address",
}
)
configurations.append(
{
"config_name": config_name + "-ubsan",
"cmake_args": cmake_args,
"cmake_target": cmake_target,
"build_only": build_only,
"build_type": build_type,
"os": os,
"architecture": architecture,
"sanitizers": "undefinedbehavior",
}
)
# TSAN is deactivated due to seg faults with latest compilers.
activate_tsan = False
if activate_tsan:
configurations.append(
{
"config_name": config_name + "-tsan-ubsan",
"cmake_args": cmake_args,
"cmake_target": cmake_target,
"build_only": build_only,
"build_type": build_type,
"os": os,
"architecture": architecture,
"sanitizers": "thread,undefinedbehavior",
}
entries.append(
MatrixEntry(
config_name=name,
image=f"ghcr.io/xrplf/xrpld/nix-{distro}:{linux.image_tag}",
cmake_args=get_cmake_args(build_type, cfg.extra_cmake_args),
cmake_target="all",
build_only=False,
build_type=build_type,
architecture=arch_info,
sanitizers=sanitizer,
compiler=compiler,
)
)
return entries
def expand_linux_packaging(linux: LinuxFile) -> list[PackagingEntry]:
"""Generate the packaging matrix from a LinuxFile's package_configs section.
Packaging uses vanilla distro images (debian:bookworm, ubi9, …) instead of
the nix-based build images, because deb/rpm tooling (debhelper, rpm-build)
is taken from the distro's archive rather than from nixpkgs. Each config
entry carries its own 'image'.
"""
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):
entries.append(
PackagingEntry(
artifact_name=f"xrpld-{distro}-{compiler}-{build_type.lower()}-amd64",
image=cfg.image,
distro=distro,
)
)
return entries
def expand_platform_matrix(pf: PlatformFile) -> list[MatrixEntry]:
"""Expand a PlatformFile (macOS or Windows) into matrix entries."""
platform_name, arch = pf.platform.split("/")
is_windows = platform_name == "windows"
entries: list[MatrixEntry] = []
for cfg in pf.configs:
for build_type in cfg.build_type:
entries.append(
MatrixEntry(
config_name=f"{platform_name}-{arch}-{build_type.lower()}",
cmake_args=get_cmake_args(build_type, cfg.extra_cmake_args),
cmake_target="install" if is_windows else "all",
build_only=cfg.build_only,
build_type=build_type,
architecture=Architecture(platform=pf.platform, runner=pf.runner),
sanitizers="",
)
else:
configurations.append(
{
"config_name": config_name,
"cmake_args": cmake_args,
"cmake_target": cmake_target,
"build_only": build_only,
"build_type": build_type,
"os": os,
"architecture": architecture,
"sanitizers": "",
}
)
return configurations
return entries
def read_config(file: Path) -> Config:
config = json.loads(file.read_text())
if (
config["architecture"] is None
or config["os"] is None
or config["build_type"] is None
or config["cmake_args"] is None
):
raise Exception("Invalid configuration file.")
return Config(**config)
# ---------------------------------------------------------------------------
# Entry point
# ---------------------------------------------------------------------------
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument(
"-a",
"--all",
help="Set to generate all configurations (generally used when merging a PR) or leave unset to generate a subset of configurations (generally used when committing to a PR).",
action="store_true",
parser = argparse.ArgumentParser(
description="Generate a CI strategy matrix for all platforms or a specific one."
)
parser.add_argument(
"-c",
"--config",
help="Path to the JSON file containing the strategy matrix configurations.",
required=False,
type=Path,
help="Platform to generate for ('linux', 'macos', or 'windows'). Defaults to all platforms.",
choices=["linux", "macos", "windows"],
default=None,
)
parser.add_argument(
"-p",
"--packaging",
help="Emit the packaging matrix (derived from the 'package' field on os entries) instead of the build/test matrix.",
help="Emit the Linux packaging matrix instead of the build/test matrix.",
action="store_true",
)
args = parser.parse_args()
matrix = []
if args.packaging:
config_path = args.config if args.config else THIS_DIR / "linux.json"
matrix += generate_packaging_matrix(read_config(config_path))
elif args.config is None or args.config == "":
matrix += generate_strategy_matrix(
args.all, read_config(THIS_DIR / "linux.json")
)
matrix += generate_strategy_matrix(
args.all, read_config(THIS_DIR / "macos.json")
)
matrix += generate_strategy_matrix(
args.all, read_config(THIS_DIR / "windows.json")
)
else:
matrix += generate_strategy_matrix(args.all, read_config(args.config))
matrix: list[MatrixEntry] | list[PackagingEntry] = []
# Generate the strategy matrix.
print(f"matrix={json.dumps({'include': matrix})}")
if args.packaging:
matrix = expand_linux_packaging(LinuxFile.load(THIS_DIR / "linux.json"))
else:
if args.config in ("linux", None):
matrix += expand_linux_matrix(LinuxFile.load(THIS_DIR / "linux.json"))
if args.config in ("macos", None):
matrix += expand_platform_matrix(PlatformFile.load(THIS_DIR / "macos.json"))
if args.config in ("windows", None):
matrix += expand_platform_matrix(
PlatformFile.load(THIS_DIR / "windows.json")
)
print(f"matrix={json.dumps({'include': [dataclasses.asdict(e) for e in matrix]})}")

View File

@@ -1,221 +1,83 @@
{
"architecture": [
{
"platform": "linux/amd64",
"runner": ["self-hosted", "Linux", "X64", "heavy"]
},
{
"platform": "linux/arm64",
"runner": ["self-hosted", "Linux", "ARM64", "heavy-arm64"]
}
],
"os": [
{
"distro_name": "debian",
"distro_version": "bookworm",
"compiler_name": "gcc",
"compiler_version": "12",
"image_sha": "4c086b9"
},
{
"distro_name": "debian",
"distro_version": "bookworm",
"compiler_name": "gcc",
"compiler_version": "13",
"image_sha": "4c086b9"
},
{
"distro_name": "debian",
"distro_version": "bookworm",
"compiler_name": "gcc",
"compiler_version": "14",
"image_sha": "4c086b9"
},
{
"distro_name": "debian",
"distro_version": "bookworm",
"compiler_name": "gcc",
"compiler_version": "15",
"image_sha": "4c086b9"
},
{
"distro_name": "debian",
"distro_version": "bookworm",
"compiler_name": "clang",
"compiler_version": "16",
"image_sha": "4c086b9"
},
{
"distro_name": "debian",
"distro_version": "bookworm",
"compiler_name": "clang",
"compiler_version": "17",
"image_sha": "4c086b9"
},
{
"distro_name": "debian",
"distro_version": "bookworm",
"compiler_name": "clang",
"compiler_version": "18",
"image_sha": "4c086b9"
},
{
"distro_name": "debian",
"distro_version": "bookworm",
"compiler_name": "clang",
"compiler_version": "19",
"image_sha": "4c086b9"
},
{
"distro_name": "debian",
"distro_version": "bookworm",
"compiler_name": "clang",
"compiler_version": "20",
"image_sha": "4c086b9"
},
{
"distro_name": "debian",
"distro_version": "trixie",
"compiler_name": "gcc",
"compiler_version": "14",
"image_sha": "4c086b9"
},
{
"distro_name": "debian",
"distro_version": "trixie",
"compiler_name": "gcc",
"compiler_version": "15",
"image_sha": "4c086b9"
},
{
"distro_name": "debian",
"distro_version": "trixie",
"compiler_name": "clang",
"compiler_version": "20",
"image_sha": "4c086b9"
},
{
"distro_name": "debian",
"distro_version": "trixie",
"compiler_name": "clang",
"compiler_version": "21",
"image_sha": "4c086b9"
},
{
"distro_name": "debian",
"distro_version": "trixie",
"compiler_name": "clang",
"compiler_version": "22",
"image_sha": "4c086b9"
},
{
"distro_name": "rhel",
"distro_version": "8",
"compiler_name": "gcc",
"compiler_version": "14",
"image_sha": "4c086b9"
},
{
"distro_name": "rhel",
"distro_version": "8",
"compiler_name": "clang",
"compiler_version": "any",
"image_sha": "4c086b9"
},
{
"distro_name": "rhel",
"distro_version": "9",
"compiler_name": "gcc",
"compiler_version": "12",
"image_sha": "4c086b9",
"package": true
},
{
"distro_name": "rhel",
"distro_version": "9",
"compiler_name": "gcc",
"compiler_version": "13",
"image_sha": "4c086b9"
},
{
"distro_name": "rhel",
"distro_version": "9",
"compiler_name": "gcc",
"compiler_version": "14",
"image_sha": "4c086b9"
},
{
"distro_name": "rhel",
"distro_version": "9",
"compiler_name": "clang",
"compiler_version": "any",
"image_sha": "4c086b9"
},
{
"distro_name": "rhel",
"distro_version": "10",
"compiler_name": "gcc",
"compiler_version": "14",
"image_sha": "4c086b9"
},
{
"distro_name": "rhel",
"distro_version": "10",
"compiler_name": "clang",
"compiler_version": "any",
"image_sha": "4c086b9"
},
{
"distro_name": "ubuntu",
"distro_version": "jammy",
"compiler_name": "gcc",
"compiler_version": "12",
"image_sha": "4c086b9",
"package": true
},
{
"distro_name": "ubuntu",
"distro_version": "noble",
"compiler_name": "gcc",
"compiler_version": "13",
"image_sha": "4c086b9"
},
{
"distro_name": "ubuntu",
"distro_version": "noble",
"compiler_name": "gcc",
"compiler_version": "14",
"image_sha": "4c086b9"
},
{
"distro_name": "ubuntu",
"distro_version": "noble",
"compiler_name": "clang",
"compiler_version": "16",
"image_sha": "4c086b9"
},
{
"distro_name": "ubuntu",
"distro_version": "noble",
"compiler_name": "clang",
"compiler_version": "17",
"image_sha": "4c086b9"
},
{
"distro_name": "ubuntu",
"distro_version": "noble",
"compiler_name": "clang",
"compiler_version": "18",
"image_sha": "4c086b9"
},
{
"distro_name": "ubuntu",
"distro_version": "noble",
"compiler_name": "clang",
"compiler_version": "19",
"image_sha": "4c086b9"
}
],
"build_type": ["Debug", "Release"],
"cmake_args": [""]
"image_tag": "sha-63ffdc3",
"configs": {
"ubuntu": [
{
"compiler": ["gcc", "clang"],
"build_type": ["Debug", "Release"],
"arch": ["amd64", "arm64"]
},
{
"compiler": ["gcc", "clang"],
"build_type": ["Debug"],
"arch": ["amd64"],
"sanitizers": ["address", "undefinedbehavior"]
},
{
"compiler": ["gcc"],
"build_type": ["Debug"],
"arch": ["amd64"],
"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"],
"arch": ["amd64"],
"suffix": "voidstar",
"extra_cmake_args": "-Dvoidstar=ON"
},
{
"compiler": ["clang"],
"build_type": ["Release"],
"arch": ["amd64"],
"suffix": "reffee",
"extra_cmake_args": "-DUNIT_TEST_REFERENCE_FEE=1000"
},
{
"compiler": ["gcc"],
"build_type": ["Debug"],
"arch": ["amd64"],
"suffix": "unity",
"extra_cmake_args": "-Dunity=ON"
}
],
"debian": [
{
"compiler": ["gcc"],
"build_type": ["Release"],
"arch": ["amd64"]
}
],
"rhel": [
{
"compiler": ["gcc"],
"build_type": ["Release"],
"arch": ["amd64"]
}
]
},
"package_configs": {
"debian": [
{
"compiler": ["gcc"],
"build_type": ["Release"],
"arch": ["amd64"],
"image": "ghcr.io/xrplf/xrpld/packaging-debian:sha-63ffdc3"
}
],
"rhel": [
{
"compiler": ["gcc"],
"build_type": ["Release"],
"arch": ["amd64"],
"image": "ghcr.io/xrplf/xrpld/packaging-rhel:sha-63ffdc3"
}
]
}
}

View File

@@ -1,19 +1,15 @@
{
"architecture": [
"platform": "macos/arm64",
"runner": ["self-hosted", "macOS", "ARM64", "mac-runner-m1"],
"configs": [
{
"platform": "macos/arm64",
"runner": ["self-hosted", "macOS", "ARM64", "mac-runner-m1"]
}
],
"os": [
"build_type": "Release",
"extra_cmake_args": "-DCMAKE_POLICY_VERSION_MINIMUM=3.5"
},
{
"distro_name": "macos",
"distro_version": "",
"compiler_name": "",
"compiler_version": "",
"image_sha": ""
"build_type": "Debug",
"extra_cmake_args": "-DCMAKE_POLICY_VERSION_MINIMUM=3.5",
"build_only": true
}
],
"build_type": ["Debug", "Release"],
"cmake_args": ["-DCMAKE_POLICY_VERSION_MINIMUM=3.5"]
]
}

View File

@@ -1,19 +1,8 @@
{
"architecture": [
{
"platform": "windows/amd64",
"runner": ["self-hosted", "Windows", "devbox"]
}
],
"os": [
{
"distro_name": "windows",
"distro_version": "",
"compiler_name": "",
"compiler_version": "",
"image_sha": ""
}
],
"build_type": ["Debug", "Release"],
"cmake_args": [""]
"platform": "windows/amd64",
"runner": ["self-hosted", "Windows", "devbox"],
"configs": [
{ "build_type": "Release" },
{ "build_type": "Debug", "build_only": true }
]
}

View File

@@ -1,101 +0,0 @@
name: Build Nix Docker image
on:
push:
branches:
- develop
paths:
- ".github/workflows/build-nix-image.yml"
- "docker/nix.Dockerfile"
- "flake.nix"
- "flake.lock"
- "nix/**"
pull_request:
paths:
- ".github/workflows/build-nix-image.yml"
- "docker/nix.Dockerfile"
- "flake.nix"
- "flake.lock"
- "nix/**"
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
defaults:
run:
shell: bash
env:
UBUNTU_VERSION: "20.04"
RHEL_VERSION: "9"
DEBIAN_VERSION: "bookworm"
jobs:
build:
name: Build and push Nix image (${{ matrix.distro }})
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
strategy:
matrix:
include:
- distro: nixos
- distro: ubuntu
- distro: rhel
- distro: debian
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Determine base image
id: vars
run: |
case "${{ matrix.distro }}" in
nixos)
echo "base_image=nixos/nix:latest" >> $GITHUB_OUTPUT
;;
ubuntu)
echo "base_image=ubuntu:${UBUNTU_VERSION}" >> $GITHUB_OUTPUT
;;
rhel)
echo "base_image=registry.access.redhat.com/ubi${RHEL_VERSION}/ubi:latest" >> $GITHUB_OUTPUT
;;
debian)
echo "base_image=debian:${DEBIAN_VERSION}" >> $GITHUB_OUTPUT
;;
esac
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
- name: Login to GitHub Container Registry
if: github.event_name == 'push'
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Docker metadata
id: meta
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0
with:
images: ghcr.io/xrplf/ci/nix-${{ matrix.distro }}
tags: |
type=sha,prefix=sha-,format=short
type=raw,value=latest
- name: Build and push
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
with:
context: .
file: docker/nix.Dockerfile
platforms: linux/amd64
push: ${{ github.event_name == 'push' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: BASE_IMAGE=${{ steps.vars.outputs.base_image }}

54
.github/workflows/build-nix-images.yml vendored Normal file
View File

@@ -0,0 +1,54 @@
name: Build Nix Docker images
on:
push:
branches:
- develop
paths:
- ".github/workflows/build-nix-images.yml"
- "flake.nix"
- "flake.lock"
- "nix/**"
pull_request:
paths:
- ".github/workflows/build-nix-images.yml"
- "flake.nix"
- "flake.lock"
- "nix/**"
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 nix-${{ matrix.distro.name }}
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
# The base images are the oldest supported version of each distro
# that we want to build images for.
distro:
- name: nixos
base_image: nixos/nix:latest
- name: ubuntu
base_image: ubuntu:20.04
- name: debian
base_image: debian:bookworm
- name: rhel
base_image: registry.access.redhat.com/ubi9/ubi:latest
uses: XRPLF/actions/.github/workflows/build-multiarch-image.yml@c1b480188519e0cad040e6aa70db1cbc5a797e07
with:
image_name: ghcr.io/xrplf/xrpld/nix-${{ matrix.distro.name }}
dockerfile: nix/docker/Dockerfile
base_image: ${{ matrix.distro.base_image }}
push: ${{ github.repository == 'XRPLF/rippled' && github.event_name == 'push' }}

View File

@@ -0,0 +1,46 @@
name: Build packaging Docker images
on:
push:
branches:
- develop
paths:
- ".github/workflows/build-packaging-images.yml"
- "package/Dockerfile"
- "package/install-packaging-tools.sh"
pull_request:
paths:
- ".github/workflows/build-packaging-images.yml"
- "package/Dockerfile"
- "package/install-packaging-tools.sh"
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 packaging-${{ matrix.distro.name }}
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
distro:
- name: debian
base_image: debian:bookworm
- name: rhel
base_image: registry.access.redhat.com/ubi9/ubi:latest
uses: XRPLF/actions/.github/workflows/build-multiarch-image.yml@c1b480188519e0cad040e6aa70db1cbc5a797e07
with:
image_name: ghcr.io/xrplf/xrpld/packaging-${{ matrix.distro.name }}
dockerfile: package/Dockerfile
base_image: ${{ matrix.distro.base_image }}
push: ${{ github.repository == 'XRPLF/rippled' && github.event_name == 'push' }}

View File

@@ -5,8 +5,17 @@ on:
types:
- checks_requested
pull_request:
types: [opened, edited, reopened, synchronize, ready_for_review]
branches: [develop]
types:
- opened
- edited
- reopened
- synchronize
- ready_for_review
branches:
- develop
- "release-*"
- "release/*"
- "staging/*"
jobs:
check_description:
@@ -14,17 +23,17 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Write PR body to file
env:
PR_BODY: ${{ github.event.pull_request.body }}
if: ${{ github.event_name == 'pull_request' }}
run: printenv PR_BODY > pr_body.md
run: printenv PR_BODY >pr_body.md
- name: Check PR description differs from template
if: ${{ github.event_name == 'pull_request' }}
run: >
python .github/scripts/check-pr-description.py
--template-file .github/pull_request_template.md
--pr-body-file pr_body.md
run: |
python .github/scripts/check-pr-description.py \
--template-file .github/pull_request_template.md \
--pr-body-file pr_body.md

View File

@@ -5,10 +5,19 @@ on:
types:
- checks_requested
pull_request:
types: [opened, edited, reopened, synchronize, ready_for_review]
branches: [develop]
types:
- opened
- edited
- reopened
- synchronize
- ready_for_review
branches:
- develop
- "release-*"
- "release/*"
- "staging/*"
jobs:
check_title:
if: ${{ github.event.pull_request.draft != true }}
uses: XRPLF/actions/.github/workflows/check-pr-title.yml@291206777251b4d493641b5afbdf7c23009d2988
uses: XRPLF/actions/.github/workflows/check-pr-title.yml@cba1f0891650baf1a9c88624dc2d72573be2eb81

View File

@@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check if PRs are dirty
uses: eps1lon/actions-label-merge-conflict@1df065ebe6e3310545d4f4c4e862e43bdca146f0 # v3.0.3
uses: eps1lon/actions-label-merge-conflict@0273be72a0bbd58fcd71d0d6c02c209b50d1e5e1 # v3.1.0
with:
dirtyLabel: "PR: has conflicts"
repoToken: "${{ secrets.GITHUB_TOKEN }}"

View File

@@ -33,7 +33,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- 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
@@ -98,7 +98,7 @@ jobs:
READY: ${{ contains(github.event.pull_request.labels.*.name, 'Ready to merge') }}
MERGE: ${{ github.event_name == 'merge_group' }}
run: |
echo "go=${{ (env.DRAFT != 'true' && env.READY == 'true') || env.FILES == 'true' || env.MERGE == 'true' }}" >> "${GITHUB_OUTPUT}"
echo "go=${{ (env.DRAFT != 'true' && env.READY == 'true') || env.FILES == 'true' || env.MERGE == 'true' }}" >>"${GITHUB_OUTPUT}"
cat "${GITHUB_OUTPUT}"
outputs:
go: ${{ steps.go.outputs.go == 'true' }}
@@ -168,9 +168,9 @@ jobs:
PR_URL: ${{ github.event.pull_request.html_url }}
run: |
gh api --method POST -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" \
/repos/xrplf/clio/dispatches -f "event_type=check_libxrpl" \
-F "client_payload[ref]=${{ needs.upload-recipe.outputs.recipe_ref }}" \
-F "client_payload[pr_url]=${PR_URL}"
/repos/xrplf/clio/dispatches -f "event_type=check_libxrpl" \
-F "client_payload[ref]=${{ needs.upload-recipe.outputs.recipe_ref }}" \
-F "client_payload[pr_url]=${PR_URL}"
passed:
if: failure() || cancelled()

View File

@@ -33,7 +33,6 @@ jobs:
with:
ccache_enabled: false
os: ${{ matrix.os }}
strategy_matrix: minimal
secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

View File

@@ -88,7 +88,6 @@ jobs:
# not identical to a regular compilation.
ccache_enabled: ${{ github.repository_owner == 'XRPLF' && !startsWith(github.ref, 'refs/heads/release') }}
os: ${{ matrix.os }}
strategy_matrix: ${{ github.event_name == 'schedule' && 'all' || 'minimal' }}
secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

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@5e942d61bf32f7557a7c159cfac4712a687b3e3a
uses: XRPLF/actions/.github/workflows/pre-commit.yml@312aaab296060ff89d7f798dcab59f019bea6e02
with:
runs_on: ubuntu-latest
container: '{ "image": "ghcr.io/xrplf/ci/tools-rippled-pre-commit:sha-41ec7c1" }'

View File

@@ -41,13 +41,13 @@ env:
jobs:
build:
runs-on: ubuntu-latest
container: ghcr.io/xrplf/ci/tools-rippled-documentation:sha-a8c7be1
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-63ffdc3
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@90f11ee655d1687824fb8793db770477d52afbab
uses: XRPLF/actions/prepare-runner@c47daebb2f9db64ffbac71b47d68a661498d5ce8
with:
enable_ccache: false
@@ -57,19 +57,11 @@ jobs:
with:
subtract: ${{ env.NPROC_SUBTRACT }}
- name: Check configuration
run: |
echo 'Checking path.'
echo ${PATH} | tr ':' '\n'
- name: Print build environment
uses: XRPLF/actions/print-build-env@59dec886e4afb05a1724443af08baccbc045b574
echo 'Checking environment variables.'
env | sort
echo 'Checking CMake version.'
cmake --version
echo 'Checking Doxygen version.'
doxygen --version
- name: Check Doxygen version
run: doxygen --version
- name: Build documentation
env:

View File

@@ -57,6 +57,12 @@ on:
type: string
default: ""
compiler:
description: 'The compiler to use ("gcc" or "clang"). Leave empty for macOS/Windows (uses system default).'
required: false
type: string
default: ""
secrets:
CODECOV_TOKEN:
description: "The Codecov token to use for uploading coverage reports."
@@ -76,7 +82,7 @@ jobs:
name: ${{ inputs.config_name }}
runs-on: ${{ fromJSON(inputs.runs_on) }}
container: ${{ inputs.image != '' && inputs.image || null }}
timeout-minutes: ${{ inputs.sanitizers != '' && 360 || 60 }}
timeout-minutes: ${{ inputs.sanitizers != '' && 360 || 90 }}
env:
# Use a namespace to keep the objects separate for each configuration.
CCACHE_NAMESPACE: ${{ inputs.config_name }}
@@ -104,16 +110,16 @@ jobs:
uses: XRPLF/actions/cleanup-workspace@c7d9ce5ebb03c752a354889ecd870cadfc2b1cd4
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@90f11ee655d1687824fb8793db770477d52afbab
uses: XRPLF/actions/prepare-runner@c47daebb2f9db64ffbac71b47d68a661498d5ce8
with:
enable_ccache: ${{ inputs.ccache_enabled }}
- name: Set ccache log file
if: ${{ inputs.ccache_enabled && runner.debug == '1' }}
run: echo "CCACHE_LOGFILE=${{ runner.temp }}/ccache.log" >> "${GITHUB_ENV}"
run: echo "CCACHE_LOGFILE=${{ runner.temp }}/ccache.log" >>"${GITHUB_ENV}"
- name: Print build environment
uses: XRPLF/actions/print-build-env@59dec886e4afb05a1724443af08baccbc045b574
@@ -124,6 +130,12 @@ jobs:
with:
subtract: ${{ inputs.nproc_subtract }}
- name: Set compiler environment (Linux)
if: ${{ runner.os == 'Linux' }}
uses: ./.github/actions/set-compiler-env
with:
compiler: ${{ inputs.compiler }}
- name: Setup Conan
env:
SANITIZERS: ${{ inputs.sanitizers }}
@@ -146,11 +158,11 @@ jobs:
CMAKE_ARGS: ${{ inputs.cmake_args }}
run: |
cmake \
-G '${{ runner.os == 'Windows' && 'Visual Studio 17 2022' || 'Ninja' }}' \
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
${CMAKE_ARGS} \
..
-G '${{ runner.os == 'Windows' && 'Visual Studio 17 2022' || 'Ninja' }}' \
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
${CMAKE_ARGS} \
..
- name: Check protocol autogen files are up-to-date
working-directory: ${{ env.BUILD_DIR }}
@@ -172,32 +184,47 @@ jobs:
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
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:
BUILD_NPROC: ${{ runner.os == 'Linux' && '16' || steps.nproc.outputs.nproc }}
BUILD_NPROC: ${{ steps.nproc.outputs.nproc }}
BUILD_TYPE: ${{ inputs.build_type }}
CMAKE_TARGET: ${{ inputs.cmake_target }}
run: |
cmake \
--build . \
--config "${BUILD_TYPE}" \
--parallel "${BUILD_NPROC}" \
--target "${CMAKE_TARGET}"
--build . \
--config "${BUILD_TYPE}" \
--parallel "${BUILD_NPROC}" \
--target "${CMAKE_TARGET}"
# This step is needed to allow running in non-Nix environments
- name: Patch binary to use default loader and remove rpath (Linux)
if: ${{ runner.os == 'Linux' && env.SANITIZERS_ENABLED == 'false' }}
run: |
loader="$(/tmp/loader-path.sh)"
patchelf --set-interpreter "${loader}" --remove-rpath "${{ env.BUILD_DIR }}/xrpld"
# We're only running aarch64 Linux builds in Ubuntu-based images, so this is kept simple
- name: Install libatomic (Linux aarch64)
if: ${{ runner.os == 'Linux' && runner.arch == 'ARM64' }}
run: |
apt update --yes
apt install -y --no-install-recommends \
libatomic1
- name: Show ccache statistics
if: ${{ inputs.ccache_enabled }}
run: |
ccache --show-stats -vv
if [ '${{ runner.debug }}' = '1' ]; then
cat "${CCACHE_LOGFILE}"
curl ${CCACHE_REMOTE_STORAGE%|*}/status || true
cat "${CCACHE_LOGFILE}"
curl ${CCACHE_REMOTE_STORAGE%|*}/status || true
fi
- name: Upload the binary (Linux)
@@ -209,15 +236,24 @@ jobs:
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
with:
name: xrpl_tests-${{ inputs.config_name }}
path: ${{ env.BUILD_DIR }}/xrpl_tests
retention-days: 3
if-no-files-found: error
- name: Export server definitions
if: ${{ runner.os != 'Windows' && !inputs.build_only && env.VOIDSTAR_ENABLED != 'true' }}
working-directory: ${{ env.BUILD_DIR }}
run: |
set -o pipefail
./xrpld --definitions | python3 -m json.tool > server_definitions.json
./xrpld --definitions | python3 -m json.tool >server_definitions.json
- name: Upload server definitions
if: ${{ github.event.repository.visibility == 'public' && inputs.config_name == 'debian-bookworm-gcc-13-amd64-release' }}
if: ${{ github.event.repository.visibility == 'public' && inputs.config_name == 'debian-gcc-release-amd64' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: server-definitions
@@ -231,10 +267,10 @@ jobs:
run: |
ldd ./xrpld
if [ "$(ldd ./xrpld | grep -E '(libstdc\+\+|libgcc)' | wc -l)" -eq 0 ]; then
echo 'The binary is statically linked.'
echo 'The binary is statically linked.'
else
echo 'The binary is dynamically linked.'
exit 1
echo 'The binary is dynamically linked.'
exit 1
fi
- name: Verify presence of instrumentation (Linux)
@@ -250,25 +286,17 @@ jobs:
run: |
ASAN_OPTS="include=${GITHUB_WORKSPACE}/sanitizers/suppressions/runtime-asan-options.txt:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/asan.supp"
if [[ "${CONFIG_NAME}" == *gcc* ]]; then
ASAN_OPTS="${ASAN_OPTS}:alloc_dealloc_mismatch=0"
ASAN_OPTS="${ASAN_OPTS}:alloc_dealloc_mismatch=0"
fi
echo "ASAN_OPTIONS=${ASAN_OPTS}" >> ${GITHUB_ENV}
echo "TSAN_OPTIONS=include=${GITHUB_WORKSPACE}/sanitizers/suppressions/runtime-tsan-options.txt:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/tsan.supp" >> ${GITHUB_ENV}
echo "UBSAN_OPTIONS=include=${GITHUB_WORKSPACE}/sanitizers/suppressions/runtime-ubsan-options.txt:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/ubsan.supp" >> ${GITHUB_ENV}
echo "LSAN_OPTIONS=include=${GITHUB_WORKSPACE}/sanitizers/suppressions/runtime-lsan-options.txt:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/lsan.supp" >> ${GITHUB_ENV}
echo "ASAN_OPTIONS=${ASAN_OPTS}" >>${GITHUB_ENV}
echo "TSAN_OPTIONS=include=${GITHUB_WORKSPACE}/sanitizers/suppressions/runtime-tsan-options.txt:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/tsan.supp" >>${GITHUB_ENV}
echo "UBSAN_OPTIONS=include=${GITHUB_WORKSPACE}/sanitizers/suppressions/runtime-ubsan-options.txt:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/ubsan.supp" >>${GITHUB_ENV}
echo "LSAN_OPTIONS=include=${GITHUB_WORKSPACE}/sanitizers/suppressions/runtime-lsan-options.txt:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/lsan.supp" >>${GITHUB_ENV}
- name: Run the separate tests
if: ${{ !inputs.build_only }}
working-directory: ${{ env.BUILD_DIR }}
# Windows locks some of the build files while running tests, and parallel jobs can collide
env:
BUILD_TYPE: ${{ inputs.build_type }}
PARALLELISM: ${{ runner.os == 'Windows' && '1' || steps.nproc.outputs.nproc }}
run: |
ctest \
--output-on-failure \
-C "${BUILD_TYPE}" \
-j "${PARALLELISM}"
working-directory: ${{ runner.os == 'Windows' && format('{0}/{1}', env.BUILD_DIR, inputs.build_type) || env.BUILD_DIR }}
run: ./xrpl_tests
- name: Run the embedded tests
if: ${{ !inputs.build_only }}
@@ -278,8 +306,26 @@ jobs:
run: |
set -o pipefail
# Coverage builds are slower due to instrumentation; use fewer parallel jobs to avoid flakiness
[ "$COVERAGE_ENABLED" = "true" ] && BUILD_NPROC=$(( BUILD_NPROC - 2 ))
./xrpld --unittest --unittest-jobs "${BUILD_NPROC}" 2>&1 | tee unittest.log
[ "$COVERAGE_ENABLED" = "true" ] && BUILD_NPROC=$((BUILD_NPROC - 2))
# The resolver/preload workaround is only correct for the ASan build:
# a regular build doesn't hit the __dn_expand interceptor bug, and must
# NOT have libasan injected. So only preload when xrpld is ASan-built.
#
# libresolv hosts getaddrinfo's resolver helpers (dn_expand, res_*). Under ASan
# these are intercepted via dlsym(RTLD_NEXT, ...), which yields a NULL pointer
# and crashes DNS resolution if libresolv isn't loaded. Linking it guarantees
# the symbols are present; it's a harmless no-op on glibc >= 2.34 (merged into
# libc) and is what the compiler driver already does for sanitizer builds.
# https://github.com/llvm/llvm-project/issues/59007
# https://github.com/google/sanitizers/issues/1592
if ldd ./xrpld | grep -q libasan; then
PRELOAD="$(gcc -print-file-name=libasan.so):/usr/lib/x86_64-linux-gnu/libresolv.so.2"
else
PRELOAD=""
fi
LD_PRELOAD="$PRELOAD" ./xrpld --unittest --unittest-jobs "${BUILD_NPROC}" 2>&1 | tee unittest.log
- name: Show test failure summary
if: ${{ failure() && !inputs.build_only }}
@@ -287,19 +333,19 @@ jobs:
WORKING_DIR: ${{ runner.os == 'Windows' && format('{0}\{1}', env.BUILD_DIR, inputs.build_type) || env.BUILD_DIR }}
run: |
if [ ! -d "${WORKING_DIR}" ]; then
echo "Working directory '${WORKING_DIR}' does not exist."
exit 0
echo "Working directory '${WORKING_DIR}' does not exist."
exit 0
fi
cd "${WORKING_DIR}"
if [ ! -f unittest.log ]; then
echo "unittest.log not found; embedded tests may not have run."
exit 0
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."
echo "Log present but no failure lines found in unittest.log."
fi
- name: Debug failure (Linux)
if: ${{ failure() && runner.os == 'Linux' && !inputs.build_only }}
@@ -317,14 +363,14 @@ jobs:
BUILD_TYPE: ${{ inputs.build_type }}
run: |
cmake \
--build . \
--config "${BUILD_TYPE}" \
--parallel "${BUILD_NPROC}" \
--target coverage
--build . \
--config "${BUILD_TYPE}" \
--parallel "${BUILD_NPROC}" \
--target coverage
- name: Upload coverage report
if: ${{ github.repository == 'XRPLF/rippled' && !inputs.build_only && env.COVERAGE_ENABLED == 'true' }}
uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
with:
disable_search: true
disable_telem: true

View File

@@ -19,13 +19,6 @@ on:
required: true
type: string
strategy_matrix:
# TODO: Support additional strategies, e.g. "ubuntu" for generating all Ubuntu configurations.
description: 'The strategy matrix to use for generating the configurations ("minimal", "all").'
required: false
type: string
default: "minimal"
secrets:
CODECOV_TOKEN:
description: "The Codecov token to use for uploading coverage reports."
@@ -37,7 +30,6 @@ jobs:
uses: ./.github/workflows/reusable-strategy-matrix.yml
with:
os: ${{ inputs.os }}
strategy_matrix: ${{ inputs.strategy_matrix }}
# Build and test the binary for each configuration.
build-test-config:
@@ -47,7 +39,6 @@ jobs:
strategy:
fail-fast: ${{ github.event_name == 'merge_group' }}
matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}
max-parallel: 10
with:
build_only: ${{ matrix.build_only }}
build_type: ${{ matrix.build_type }}
@@ -55,8 +46,9 @@ jobs:
cmake_args: ${{ matrix.cmake_args }}
cmake_target: ${{ matrix.cmake_target }}
runs_on: ${{ toJSON(matrix.architecture.runner) }}
image: ${{ contains(matrix.architecture.platform, 'linux') && format('ghcr.io/xrplf/ci/{0}-{1}:{2}-{3}-sha-{4}', matrix.os.distro_name, matrix.os.distro_version, matrix.os.compiler_name, matrix.os.compiler_version, matrix.os.image_sha) || '' }}
image: ${{ matrix.image || '' }}
config_name: ${{ matrix.config_name }}
sanitizers: ${{ matrix.sanitizers }}
compiler: ${{ matrix.compiler || '' }}
secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

View File

@@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Check levelization
run: python .github/scripts/levelization/generate.py
- name: Check for differences
@@ -38,9 +38,9 @@ jobs:
run: |
DIFF=$(git status --porcelain)
if [ -n "${DIFF}" ]; then
# Print the differences to give the contributor a hint about what to
# expect when running levelization on their own machine.
git diff
echo "${MESSAGE}"
exit 1
# Print the differences to give the contributor a hint about what to
# expect when running levelization 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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Check definitions
run: .github/scripts/rename/definitions.sh .
- name: Check copyright notices
@@ -48,9 +48,9 @@ jobs:
run: |
DIFF=$(git status --porcelain)
if [ -n "${DIFF}" ]; then
# Print the differences to give the contributor a hint about what to
# expect when running the renaming scripts on their own machine.
git diff
echo "${MESSAGE}"
exit 1
# Print the differences to give the contributor a hint about what to
# expect when running the renaming scripts on their own machine.
git diff
echo "${MESSAGE}"
exit 1
fi

View File

@@ -29,23 +29,23 @@ jobs:
if: ${{ inputs.check_only_changed }}
permissions:
contents: read
uses: XRPLF/actions/.github/workflows/determine-tidy-files.yml@224f3c48d3014d082a1129237b8291ff0b0a331f
uses: XRPLF/actions/.github/workflows/determine-tidy-files.yml@312aaab296060ff89d7f798dcab59f019bea6e02
run-clang-tidy:
name: Run clang tidy
needs: [determine-files]
if: ${{ always() && !cancelled() && (!inputs.check_only_changed || needs.determine-files.outputs.cpp_changed_files != '' || needs.determine-files.outputs.clang_tidy_config_changed == 'true') }}
runs-on: ["self-hosted", "Linux", "X64", "heavy"]
container: "ghcr.io/xrplf/ci/debian-trixie:clang-21-sha-53033a2"
container: "ghcr.io/xrplf/xrpld/nix-debian:sha-63ffdc3"
permissions:
contents: read
issues: write
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@90f11ee655d1687824fb8793db770477d52afbab
uses: XRPLF/actions/prepare-runner@c47daebb2f9db64ffbac71b47d68a661498d5ce8
with:
enable_ccache: false
@@ -56,6 +56,11 @@ jobs:
uses: XRPLF/actions/get-nproc@cf0433aa74563aead044a1e395610c96d65a37cf
id: nproc
- name: Set compiler environment
uses: ./.github/actions/set-compiler-env
with:
compiler: clang
- name: Setup Conan
uses: ./.github/actions/setup-conan
@@ -70,13 +75,13 @@ jobs:
working-directory: ${{ env.BUILD_DIR }}
run: |
cmake \
-G 'Ninja' \
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
-Dtests=ON \
-Dwerr=ON \
-Dxrpld=ON \
..
-G 'Ninja' \
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
-Dtests=ON \
-Dwerr=ON \
-Dxrpld=ON \
..
# clang-tidy needs headers generated from proto files
- name: Build libxrpl.libpb
@@ -133,7 +138,7 @@ jobs:
- name: Write issue header
if: ${{ steps.run_clang_tidy.outcome != 'success' }}
run: |
cat > "${ISSUE_FILE}" <<EOF
cat >"${ISSUE_FILE}" <<EOF
## Clang-tidy Check Failed
### Clang-tidy Output:
@@ -144,30 +149,30 @@ jobs:
if: ${{ steps.run_clang_tidy.outcome != 'success' }}
run: |
if [ -f "${OUTPUT_FILE}" ]; then
# Extract lines containing 'error:', 'warning:', or 'note:'
grep -E '(error:|warning:|note:)' "${OUTPUT_FILE}" > filtered-output.txt || true
# Extract lines containing 'error:', 'warning:', or 'note:'
grep -E '(error:|warning:|note:)' "${OUTPUT_FILE}" >filtered-output.txt || true
# If filtered output is empty, use original (might be a different error format)
if [ ! -s filtered-output.txt ]; then
cp "${OUTPUT_FILE}" filtered-output.txt
fi
# If filtered output is empty, use original (might be a different error format)
if [ ! -s filtered-output.txt ]; then
cp "${OUTPUT_FILE}" filtered-output.txt
fi
# Truncate if too large
head -c 60000 filtered-output.txt >> "${ISSUE_FILE}"
if [ "$(wc -c < filtered-output.txt)" -gt 60000 ]; then
echo "" >> "${ISSUE_FILE}"
echo "... (output truncated, see artifacts for full output)" >> "${ISSUE_FILE}"
fi
# Truncate if too large
head -c 60000 filtered-output.txt >>"${ISSUE_FILE}"
if [ "$(wc -c <filtered-output.txt)" -gt 60000 ]; then
echo "" >>"${ISSUE_FILE}"
echo "... (output truncated, see artifacts for full output)" >>"${ISSUE_FILE}"
fi
rm filtered-output.txt
rm filtered-output.txt
else
echo "No output file found" >> "${ISSUE_FILE}"
echo "No output file found" >>"${ISSUE_FILE}"
fi
- name: Append issue footer
if: ${{ steps.run_clang_tidy.outcome != 'success' }}
run: |
cat >> "${ISSUE_FILE}" <<EOF
cat >>"${ISSUE_FILE}" <<EOF
\`\`\`
---
@@ -176,7 +181,7 @@ jobs:
- name: Create issue
if: ${{ steps.run_clang_tidy.outcome != 'success' && inputs.create_issue_on_failure }}
uses: XRPLF/actions/create-issue@36d450d12d301e8410c1b7936e5de70c291cbe36
uses: XRPLF/actions/create-issue@2b8bc36af85b88bca0dd7bfac2e2dc05f94ad712
with:
title: "Clang-tidy check failed"
body_file: ${{ env.ISSUE_FILE }}

View File

@@ -1,8 +1,7 @@
# Build Linux packages (DEB and RPM) from pre-built binary artifacts.
# Discovers which configurations to package from linux.json (os entries
# with "package": true) and fans out one job per entry. Today only
# linux/amd64 is emitted; the architecture is hardcoded both here
# (runner) and in generate.py.
# 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:
@@ -28,18 +27,17 @@ jobs:
matrix: ${{ steps.generate.outputs.matrix }}
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: 3.13
python-version: "3.13"
- name: Generate packaging matrix
id: generate
working-directory: .github/scripts/strategy-matrix
run: |
./generate.py --packaging --config=linux.json >> "${GITHUB_OUTPUT}"
run: ./generate.py --packaging >>"${GITHUB_OUTPUT}"
generate-version:
runs-on: ubuntu-latest
@@ -47,7 +45,7 @@ jobs:
version: ${{ steps.version.outputs.version }}
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
sparse-checkout: |
.github/actions/generate-version
@@ -66,12 +64,12 @@ jobs:
permissions:
contents: read
runs-on: ["self-hosted", "Linux", "X64", "heavy"]
container: ${{ format('ghcr.io/xrplf/ci/{0}-{1}:{2}-{3}-sha-{4}', matrix.os.distro_name, matrix.os.distro_version, matrix.os.compiler_name, matrix.os.compiler_version, matrix.os.image_sha) }}
container: ${{ matrix.image }}
timeout-minutes: 30
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Download pre-built binary
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1

View File

@@ -4,15 +4,9 @@ on:
workflow_call:
inputs:
os:
description: 'The operating system to use for the build ("linux", "macos", "windows").'
description: 'The operating system to use for the build ("linux", "macos", "windows", or empty for all).'
required: false
type: string
strategy_matrix:
# TODO: Support additional strategies, e.g. "ubuntu" for generating all Ubuntu configurations.
description: 'The strategy matrix to use for generating the configurations ("minimal", "all").'
required: false
type: string
default: "minimal"
outputs:
matrix:
description: "The generated strategy matrix."
@@ -29,17 +23,16 @@ jobs:
matrix: ${{ steps.generate.outputs.matrix }}
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: 3.13
python-version: "3.13"
- name: Generate strategy matrix
working-directory: .github/scripts/strategy-matrix
id: generate
env:
GENERATE_CONFIG: ${{ inputs.os != '' && format('--config={0}.json', inputs.os) || '' }}
GENERATE_OPTION: ${{ inputs.strategy_matrix == 'all' && '--all' || '' }}
run: ./generate.py ${GENERATE_OPTION} ${GENERATE_CONFIG} >> "${GITHUB_OUTPUT}"
GENERATE_CONFIG: ${{ inputs.os != '' && format('--config={0}', inputs.os) || '' }}
run: ./generate.py ${GENERATE_CONFIG} >>"${GITHUB_OUTPUT}"

View File

@@ -40,10 +40,10 @@ defaults:
jobs:
upload:
runs-on: ubuntu-latest
container: ghcr.io/xrplf/ci/ubuntu-noble:gcc-13-sha-5dd7158
container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-63ffdc3
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Generate build version number
id: version

View File

@@ -48,8 +48,6 @@ jobs:
# Generate the strategy matrix to be used by the following job.
generate-matrix:
uses: ./.github/workflows/reusable-strategy-matrix.yml
with:
strategy_matrix: ${{ github.event_name == 'pull_request' && 'minimal' || 'all' }}
# Build and upload the dependencies for each configuration.
run-upload-conan-deps:
@@ -58,19 +56,18 @@ jobs:
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}
max-parallel: 10
runs-on: ${{ matrix.architecture.runner }}
container: ${{ contains(matrix.architecture.platform, 'linux') && format('ghcr.io/xrplf/ci/{0}-{1}:{2}-{3}-sha-{4}', matrix.os.distro_name, matrix.os.distro_version, matrix.os.compiler_name, matrix.os.compiler_version, matrix.os.image_sha) || null }}
container: ${{ matrix.image || null }}
steps:
- name: Cleanup workspace (macOS and Windows)
if: ${{ runner.os == 'macOS' || runner.os == 'Windows' }}
uses: XRPLF/actions/cleanup-workspace@c7d9ce5ebb03c752a354889ecd870cadfc2b1cd4
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Prepare runner
uses: XRPLF/actions/prepare-runner@90f11ee655d1687824fb8793db770477d52afbab
uses: XRPLF/actions/prepare-runner@c47daebb2f9db64ffbac71b47d68a661498d5ce8
with:
enable_ccache: false
@@ -83,6 +80,12 @@ jobs:
with:
subtract: ${{ env.NPROC_SUBTRACT }}
- name: Set compiler environment (Linux)
if: ${{ runner.os == 'Linux' }}
uses: ./.github/actions/set-compiler-env
with:
compiler: ${{ matrix.compiler }}
- name: Setup Conan
env:
SANITIZERS: ${{ matrix.sanitizers }}

View File

@@ -37,37 +37,50 @@ repos:
exclude: ^include/xrpl/protocol_autogen/(transactions|ledger_entries)/
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: cd481d7b0bfb5c7b3090c21846317f9a8262e891 # frozen: v22.1.0
rev: dd18dad857d6133e90bbe478f4f2f22ec0030269 # frozen: v22.1.5
hooks:
- id: clang-format
args: [--style=file]
"types_or": [c++, c, proto]
exclude: ^include/xrpl/protocol_autogen/(transactions|ledger_entries)/
- repo: https://github.com/BlankSpruce/gersemi
rev: 0.26.0
- repo: https://github.com/BlankSpruce/gersemi-pre-commit
rev: faadd6a9d852369ca94f4d15b2404c967ba8cb01 # frozen: 0.27.6
hooks:
- id: gersemi
- repo: https://github.com/rbubley/mirrors-prettier
rev: c2bc67fe8f8f549cc489e00ba8b45aa18ee713b1 # frozen: v3.8.1
rev: 515f543f5718ebfd6ce22e16708bb32c68ff96e1 # frozen: v3.8.3
hooks:
- id: prettier
args: [--end-of-line=auto]
- repo: https://github.com/psf/black-pre-commit-mirror
rev: ea488cebbfd88a5f50b8bd95d5c829d0bb76feb8 # frozen: 26.1.0
rev: 4160603246a6b365d4a2af661c6d71b0a0f50478 # frozen: 26.5.1
hooks:
- id: black
- repo: https://github.com/openstack/bashate
rev: 5798d24d571676fc407e81df574c1ef57b520f23 # frozen: 2.1.1
- repo: https://github.com/scop/pre-commit-shfmt
rev: 05c1426671b9237fb5e1444dd63aa5731bec0dfb # frozen: v3.13.1-1
hooks:
- id: bashate
args: ["--ignore=E006"]
- id: shfmt
args: [--write, --indent=4, --case-indent=true]
- repo: local
hooks:
- id: format-inline-bash-workflows
name: "format `run:` blocks in workflows/actions"
entry: ./.github/scripts/format-inline-bash.py
language: python
files: ^\.github/(workflows|actions)/.*\.ya?ml$
- id: format-inline-bash-markdown
name: "format ```bash blocks in markdown"
entry: ./.github/scripts/format-inline-bash.py
language: python
files: \.md$
- repo: https://github.com/streetsidesoftware/cspell-cli
rev: a42085ade523f591dca134379a595e7859986445 # frozen: v9.7.0
rev: 4643f154907327ee0a2c7038f0296e0dd77d9776 # frozen: v10.0.0
hooks:
- id: cspell # Spell check changed files
exclude: |

View File

@@ -45,14 +45,14 @@ found here](./docs/build/environment.md).
It is possible to build with Conan 1.60+, but the instructions are
significantly different, which is why we are not recommending it.
`xrpld` is written in the C++20 dialect and includes the `<concepts>` header.
The [minimum compiler versions][2] required are:
`xrpld` is written in the C++23 dialect and includes the `<concepts>` header.
The [tested compiler versions][2] are:
| Compiler | Version |
| ----------- | --------- |
| GCC | 12 |
| Clang | 16 |
| Apple Clang | 16 |
| GCC | 15 |
| Clang | 22 |
| Apple Clang | 17 |
| MSVC | 19.44[^3] |
### Linux
@@ -151,8 +151,8 @@ git init
git remote add origin git@github.com:XRPLF/conan-center-index.git
git sparse-checkout init
for recipe in "${recipes[@]}"; do
echo "Checking out recipe '${recipe}'..."
git sparse-checkout add recipes/${recipe}
echo "Checking out recipe '${recipe}'..."
git sparse-checkout add recipes/${recipe}
done
git fetch origin master
git checkout master
@@ -180,7 +180,7 @@ the new recipe will be automatically pulled from the official Conan Center.
If you see an error similar to the following after running `conan profile show`:
```bash
```text
ERROR: Invalid setting '17' is not a valid 'settings.compiler.version' value.
Possible values are ['5.0', '5.1', '6.0', '6.1', '7.0', '7.3', '8.0', '8.1',
'9.0', '9.1', '10.0', '11.0', '12.0', '13', '13.0', '13.1', '14', '14.0', '15',
@@ -232,11 +232,11 @@ name and then creating a new `default` profile for a different compiler.
#### Select language
The default profile created by Conan will typically select different C++ dialect
than C++20 used by this project. You should set `20` in the profile line
than C++23 used by this project. You should set `23` in the profile line
starting with `compiler.cppstd=`. For example:
```bash
sed -i.bak -e 's|^compiler\.cppstd=.*$|compiler.cppstd=20|' $(conan config home)/profiles/default
sed -i.bak -e 's|^compiler\.cppstd=.*$|compiler.cppstd=23|' $(conan config home)/profiles/default
```
#### Select standard library in Linux
@@ -427,16 +427,19 @@ install ccache --version 4.11.3 --allow-downgrade`.
Single-config generators:
```
cmake --build .
cmake --build . --parallel N
```
Multi-config generators:
```
cmake --build . --config Release
cmake --build . --config Debug
cmake --build . --config Release --parallel N
cmake --build . --config Debug --parallel N
```
Replace the `--parallel` parameter N with the desired number of parallel jobs. A common starting point is half of the number of available CPU
cores.
5. Test xrpld.
Single-config generators:

View File

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

View File

@@ -1,8 +1,8 @@
#!/bin/bash
if [[ $# -ne 1 || "$1" == "--help" || "$1" == "-h" ]]; then
name=$( basename $0 )
cat <<- USAGE
name=$(basename $0)
cat <<-USAGE
Usage: $name <username>
Where <username> is the Github username of the upstream repo. e.g. XRPLF
@@ -14,7 +14,7 @@ fi
shift
user="$1"
# Get the origin URL. Expect it be an SSH-style URL
origin=$( git remote get-url origin )
origin=$(git remote get-url origin)
if [[ "${origin}" == "" ]]; then
echo Invalid origin remote >&2
exit 1
@@ -22,11 +22,11 @@ fi
# echo "Origin: ${origin}"
# Parse the origin
ifs_orig="${IFS}"
IFS=':' read remote originpath <<< "${origin}"
IFS=':' read remote originpath <<<"${origin}"
# echo "Remote: ${remote}, Originpath: ${originpath}"
IFS='@' read sshuser server <<< "${remote}"
IFS='@' read sshuser server <<<"${remote}"
# echo "SSHUser: ${sshuser}, Server: ${server}"
IFS='/' read originuser repo <<< "${originpath}"
IFS='/' read originuser repo <<<"${originpath}"
# echo "Originuser: ${originuser}, Repo: ${repo}"
if [[ "${sshuser}" == "" || "${server}" == "" || "${originuser}" == "" || "${repo}" == "" ]]; then
echo "Can't parse origin URL: ${origin}" >&2
@@ -35,9 +35,9 @@ fi
upstream="https://${server}/${user}/${repo}"
upstreampush="${remote}:${user}/${repo}"
upstreamgroup="upstream upstream-push"
current=$( git remote get-url upstream 2>/dev/null )
currentpush=$( git remote get-url upstream-push 2>/dev/null )
currentgroup=$( git config remotes.upstreams )
current=$(git remote get-url upstream 2>/dev/null)
currentpush=$(git remote get-url upstream-push 2>/dev/null)
currentgroup=$(git config remotes.upstreams)
if [[ "${current}" == "${upstream}" ]]; then
echo "Upstream already set up correctly. Skip"
elif [[ -n "${current}" && "${current}" != "${upstream}" && "${current}" != "${upstreampush}" ]]; then
@@ -45,9 +45,9 @@ elif [[ -n "${current}" && "${current}" != "${upstream}" && "${current}" != "${u
else
if [[ "${current}" == "${upstreampush}" ]]; then
echo "Upstream set to dangerous push URL. Update."
_run git remote rename upstream upstream-push || \
_run git remote remove upstream
currentpush=$( git remote get-url upstream-push 2>/dev/null )
_run git remote rename upstream upstream-push ||
_run git remote remove upstream
currentpush=$(git remote get-url upstream-push 2>/dev/null)
fi
_run git remote add upstream "${upstream}"
fi

View File

@@ -1,8 +1,8 @@
#!/bin/bash
if [[ $# -lt 3 || "$1" == "--help" || "$1" = "-h" ]]; then
name=$( basename $0 )
cat <<- USAGE
name=$(basename $0)
cat <<-USAGE
Usage: $name workbranch base/branch user/branch [user/branch [...]]
* workbranch will be created locally from base/branch
@@ -16,7 +16,7 @@ fi
work="$1"
shift
branches=( $( echo "${@}" | sed "s/:/\//" ) )
branches=($(echo "${@}" | sed "s/:/\//"))
base="${branches[0]}"
unset branches[0]
@@ -24,10 +24,10 @@ set -e
users=()
for b in "${branches[@]}"; do
users+=( $( echo $b | cut -d/ -f1 ) )
users+=($(echo $b | cut -d/ -f1))
done
users=( $( printf '%s\n' "${users[@]}" | sort -u ) )
users=($(printf '%s\n' "${users[@]}" | sort -u))
git fetch --multiple upstreams "${users[@]}"
git checkout -B "$work" --no-track "$base"
@@ -40,7 +40,7 @@ done
# Make sure the commits look right
git log --show-signature "$base..HEAD"
parts=( $( echo $base | sed "s/\// /" ) )
parts=($(echo $base | sed "s/\// /"))
repo="${parts[0]}"
b="${parts[1]}"
push=$repo
@@ -50,7 +50,7 @@ fi
if [[ "$repo" == "upstream" ]]; then
repo="upstreams"
fi
cat << PUSH
cat <<PUSH
-------------------------------------------------------------------
This script will not push. Verify everything is correct, then push

View File

@@ -1,8 +1,8 @@
#!/bin/bash
if [[ $# -ne 3 || "$1" == "--help" || "$1" = "-h" ]]; then
name=$( basename $0 )
cat <<- USAGE
name=$(basename $0)
cat <<-USAGE
Usage: $name workbranch base/branch version
* workbranch will be created locally from base/branch. If it exists,
@@ -16,7 +16,7 @@ fi
work="$1"
shift
base=$( echo "$1" | sed "s/:/\//" )
base=$(echo "$1" | sed "s/:/\//")
shift
version=$1
@@ -28,16 +28,16 @@ git fetch upstreams
git checkout -B "${work}" --no-track "${base}"
push=$( git rev-parse --abbrev-ref --symbolic-full-name '@{push}' \
2>/dev/null ) || true
push=$(git rev-parse --abbrev-ref --symbolic-full-name '@{push}' \
2>/dev/null) || true
if [[ "${push}" != "" ]]; then
echo "Warning: ${push} may already exist."
fi
build=$( find -name BuildInfo.cpp )
sed 's/\(^.*versionString =\).*$/\1 "'${version}'"/' ${build} > version.cpp && \
diff "${build}" version.cpp && exit 1 || \
mv -vi version.cpp ${build}
build=$(find -name BuildInfo.cpp)
sed 's/\(^.*versionString =\).*$/\1 "'${version}'"/' ${build} >version.cpp &&
diff "${build}" version.cpp && exit 1 ||
mv -vi version.cpp ${build}
git diff
@@ -47,7 +47,7 @@ git commit -S -m "Set version to ${version}"
git log --oneline --first-parent ${base}^..
cat << PUSH
cat <<PUSH
-------------------------------------------------------------------
This script will not push. Verify everything is correct, then push

View File

@@ -168,7 +168,13 @@ def main():
if not os.environ.get("TIDY"):
return 0
repo_root = Path(__file__).parent.parent
repo_root = Path(
subprocess.check_output(
["git", "rev-parse", "--show-toplevel"],
cwd=Path(__file__).parent,
text=True,
).strip()
)
files = staged_files(repo_root)
if not files:
return 0

View File

@@ -953,6 +953,21 @@
#
# Optional keys for NuDB and RocksDB:
#
# cache_size Size of cache for database records. Default is 16384.
# Setting this value to 0 will use the default value.
#
# cache_age Length of time in minutes to keep database records
# cached. Default is 5 minutes. Setting this value to
# 0 will use the default value.
#
# Note: if cache_size or cache_age is not specified,
# default values will be used for the unspecified
# parameter.
#
# Note: the cache will not be created if online_delete
# is specified, because the rotating NodeStore does
# not use this cache).
#
# fast_load Boolean. If set, load the last persisted ledger
# from disk upon process start before syncing to
# the network. This is likely to improve performance

View File

@@ -1,22 +0,0 @@
include(isolate_headers)
function(xrpl_add_test name)
set(target ${PROJECT_NAME}.test.${name})
file(
GLOB_RECURSE sources
CONFIGURE_DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/${name}/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/${name}.cpp"
)
add_executable(${target} ${ARGN} ${sources})
isolate_headers(
${target}
"${CMAKE_SOURCE_DIR}"
"${CMAKE_SOURCE_DIR}/tests/${name}"
PRIVATE
)
add_test(NAME ${target} COMMAND ${target})
endfunction()

View File

@@ -145,13 +145,39 @@ else()
INTERFACE
-rdynamic
$<$<BOOL:${is_linux}>:-Wl,-z,relro,-z,now,--build-id>
# link to static libc/c++ iff: * static option set and * NOT APPLE (AppleClang does not support static
# libc/c++) and * NOT SANITIZERS (sanitizers typically don't work with static libc/c++)
$<$<AND:$<BOOL:${static}>,$<NOT:$<BOOL:${APPLE}>>,$<NOT:$<BOOL:${SANITIZERS_ENABLED}>>>:
# link to static libc/c++ if:
# * static option set and
# * NOT APPLE (AppleClang does not support static libc/c++)
$<$<AND:$<BOOL:${static}>,$<NOT:$<BOOL:${APPLE}>>>:
-static-libstdc++
-static-libgcc
>
)
# Keep -stdlib=libstdc++ off the compile commands, but preserve it for linking.
#
# Conan turns `compiler.libcxx=libstdc++` into `-stdlib=libstdc++` and puts it in
# CMAKE_CXX_FLAGS, which CMake passes to BOTH compile and link steps. On a normal Clang
# the compile step consumes it while choosing the C++ stdlib include paths. The Nixpkgs
# 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/"
AND is_linux
AND is_clang
AND CMAKE_CXX_FLAGS MATCHES "stdlib=libstdc"
)
string(
REPLACE "-stdlib=libstdc++"
""
CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS}"
)
string(STRIP "${CMAKE_CXX_FLAGS}" CMAKE_CXX_FLAGS)
add_link_options($<$<LINK_LANGUAGE:CXX>:-stdlib=libstdc++>)
endif()
endif()
# Antithesis instrumentation will only be built and deployed using machines running Linux.

View File

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

View File

@@ -47,7 +47,7 @@ setup_target_for_coverage_gcovr(
"include/xrpl/beast/test"
"include/xrpl/beast/unit_test"
"${CMAKE_BINARY_DIR}/pb-xrpl.libpb"
DEPENDENCIES xrpld xrpl.tests
DEPENDENCIES xrpld xrpl_tests
)
add_code_coverage_to_target(opts INTERFACE)

View File

@@ -0,0 +1,13 @@
# Python dependencies for XRP Ledger code generation scripts
#
# These packages are required to run the code generation scripts that
# parse macro files and generate C++ wrapper classes.
# C preprocessor for Python - used to preprocess macro files
pcpp>=1.30
# Parser combinator library - used to parse the macro DSL
pyparsing>=3.0.0
# Template engine - used to generate C++ code from templates
Mako>=1.2.2

View File

@@ -1,13 +1,105 @@
# Python dependencies for XRP Ledger code generation scripts
#
# These packages are required to run the code generation scripts that
# parse macro files and generate C++ wrapper classes.
# C preprocessor for Python - used to preprocess macro files
pcpp>=1.30
# Parser combinator library - used to parse the macro DSL
pyparsing>=3.0.0
# Template engine - used to generate C++ code from templates
Mako>=1.2.2
# This file was autogenerated by uv via the following command:
# uv pip compile requirements.in --generate-hashes --output-file requirements.txt
mako==1.3.12 \
--hash=sha256:8f61569480282dbf557145ce441e4ba888be453c30989f879f0d652e39f53ea9 \
--hash=sha256:9f778e93289bd410bb35daadeb4fc66d95a746f0b75777b942088b7fd7af550a
# via -r requirements.in
markupsafe==3.0.3 \
--hash=sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f \
--hash=sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a \
--hash=sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf \
--hash=sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19 \
--hash=sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf \
--hash=sha256:0f4b68347f8c5eab4a13419215bdfd7f8c9b19f2b25520968adfad23eb0ce60c \
--hash=sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175 \
--hash=sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219 \
--hash=sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb \
--hash=sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6 \
--hash=sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab \
--hash=sha256:15d939a21d546304880945ca1ecb8a039db6b4dc49b2c5a400387cdae6a62e26 \
--hash=sha256:177b5253b2834fe3678cb4a5f0059808258584c559193998be2601324fdeafb1 \
--hash=sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce \
--hash=sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218 \
--hash=sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634 \
--hash=sha256:1ba88449deb3de88bd40044603fafffb7bc2b055d626a330323a9ed736661695 \
--hash=sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad \
--hash=sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73 \
--hash=sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c \
--hash=sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe \
--hash=sha256:2a15a08b17dd94c53a1da0438822d70ebcd13f8c3a95abe3a9ef9f11a94830aa \
--hash=sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559 \
--hash=sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa \
--hash=sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37 \
--hash=sha256:3537e01efc9d4dccdf77221fb1cb3b8e1a38d5428920e0657ce299b20324d758 \
--hash=sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f \
--hash=sha256:38664109c14ffc9e7437e86b4dceb442b0096dfe3541d7864d9cbe1da4cf36c8 \
--hash=sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d \
--hash=sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c \
--hash=sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97 \
--hash=sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a \
--hash=sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19 \
--hash=sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9 \
--hash=sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9 \
--hash=sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc \
--hash=sha256:591ae9f2a647529ca990bc681daebdd52c8791ff06c2bfa05b65163e28102ef2 \
--hash=sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4 \
--hash=sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354 \
--hash=sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50 \
--hash=sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698 \
--hash=sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9 \
--hash=sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b \
--hash=sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc \
--hash=sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115 \
--hash=sha256:7c3fb7d25180895632e5d3148dbdc29ea38ccb7fd210aa27acbd1201a1902c6e \
--hash=sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485 \
--hash=sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f \
--hash=sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12 \
--hash=sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025 \
--hash=sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009 \
--hash=sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d \
--hash=sha256:949b8d66bc381ee8b007cd945914c721d9aba8e27f71959d750a46f7c282b20b \
--hash=sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a \
--hash=sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5 \
--hash=sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f \
--hash=sha256:a320721ab5a1aba0a233739394eb907f8c8da5c98c9181d1161e77a0c8e36f2d \
--hash=sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1 \
--hash=sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287 \
--hash=sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6 \
--hash=sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f \
--hash=sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581 \
--hash=sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed \
--hash=sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b \
--hash=sha256:c0c0b3ade1c0b13b936d7970b1d37a57acde9199dc2aecc4c336773e1d86049c \
--hash=sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026 \
--hash=sha256:c4ffb7ebf07cfe8931028e3e4c85f0357459a3f9f9490886198848f4fa002ec8 \
--hash=sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676 \
--hash=sha256:d2ee202e79d8ed691ceebae8e0486bd9a2cd4794cec4824e1c99b6f5009502f6 \
--hash=sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e \
--hash=sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d \
--hash=sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d \
--hash=sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01 \
--hash=sha256:df2449253ef108a379b8b5d6b43f4b1a8e81a061d6537becd5582fba5f9196d7 \
--hash=sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419 \
--hash=sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795 \
--hash=sha256:e2103a929dfa2fcaf9bb4e7c091983a49c9ac3b19c9061b6d5427dd7d14d81a1 \
--hash=sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5 \
--hash=sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d \
--hash=sha256:e8fc20152abba6b83724d7ff268c249fa196d8259ff481f3b1476383f8f24e42 \
--hash=sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe \
--hash=sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda \
--hash=sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e \
--hash=sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737 \
--hash=sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523 \
--hash=sha256:f42d0984e947b8adf7dd6dde396e720934d12c506ce84eea8476409563607591 \
--hash=sha256:f71a396b3bf33ecaa1626c255855702aca4d3d9fea5e051b41ac59a9c1c41edc \
--hash=sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a \
--hash=sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50
# via mako
pcpp==1.30 \
--hash=sha256:05fe08292b6da57f385001c891a87f40d6aa7f46787b03e8ba326d20a3297c6e \
--hash=sha256:5af9fbce55f136d7931ae915fae03c34030a3b36c496e72d9636cedc8e2543a1
# via -r requirements.in
pyparsing==3.3.2 \
--hash=sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d \
--hash=sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc
# via -r requirements.in

View File

@@ -33,7 +33,7 @@ public:
* @brief Construct a ${name} ledger entry wrapper from an existing SLE object.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
explicit ${name}(std::shared_ptr<SLE const> sle)
explicit ${name}(SLE::const_pointer sle)
: LedgerEntryBase(std::move(sle))
{
// Verify ledger entry type
@@ -168,7 +168,7 @@ ${field['typeData']['setter_type']} ${field['paramName']}${',' if i < len(requir
* @param sle The existing ledger entry to copy from.
* @throws std::runtime_error if the ledger entry type doesn't match.
*/
${name}Builder(std::shared_ptr<SLE const> sle)
${name}Builder(SLE::const_pointer sle)
{
if (sle->at(sfLedgerEntryType) != ${tag})
{

View File

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

View File

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

View File

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

View File

@@ -1 +1,8 @@
{% set os = detect_api.detect_os() %}
include(sanitizers)
[conf]
{% if os == "Linux" %}
user.package:libc_version=2.31
tools.info.package_id:confs+=["user.package:libc_version"]
{% endif %}

View File

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

View File

@@ -50,6 +50,7 @@ words:
- AMMXRP
- amt
- amts
- archs
- asnode
- asynchrony
- attestation
@@ -93,6 +94,7 @@ words:
- daria
- dcmake
- dearmor
- dedented
- deleteme
- demultiplexer
- deserializaton
@@ -133,6 +135,7 @@ words:
- iou
- ious
- isrdc
- isystem
- itype
- jemalloc
- jlog
@@ -199,11 +202,13 @@ words:
- nonxrp
- noreplace
- noripple
- nostdinc
- notifempty
- nudb
- nullptr
- nunl
- Nyffenegger
- onlatest
- ostr
- pargs
- partitioner
@@ -254,6 +259,7 @@ words:
- sfields
- shamap
- shamapitem
- shfmt
- shlibs
- sidechain
- SIGGOOD
@@ -298,6 +304,7 @@ words:
- unauthorizing
- unergonomic
- unfetched
- unfindable
- unflatten
- unfund
- unimpair

View File

@@ -1,66 +0,0 @@
ARG BASE_IMAGE=nixos/nix:latest
# Nix builder
FROM nixos/nix:latest AS builder-source
RUN mkdir -p ~/.config/nix && \
echo "experimental-features = nix-command flakes" >> ~/.config/nix/nix.conf
# Copy our source and setup our working dir.
COPY nix/ci-env.nix /tmp/build/nix/ci-env.nix
COPY nix/packages.nix /tmp/build/nix/packages.nix
COPY nix/utils.nix /tmp/build/nix/utils.nix
COPY flake.nix /tmp/build/
COPY flake.lock /tmp/build/
WORKDIR /tmp/build
FROM builder-source AS builder
# Build our Nix CI environment (all build tools in a single store path)
RUN nix \
--option filter-syscalls false \
build
# Copy the Nix store closure into a directory. The Nix store closure is the
# entire set of Nix store values that we need for our build.
RUN mkdir /tmp/nix-store-closure && \
cp -R $(nix-store -qR result/) /tmp/nix-store-closure
# Final image
FROM ${BASE_IMAGE}
# bash is not located at /bin/bash in nixos/nix, so we need to create a symlink to it.
RUN if [ -d /nix ]; then \
ln -s /root/.nix-profile/bin/bash /bin/bash; \
fi
# Use Bash as the default shell for RUN commands, using the options
# `set -o errexit -o pipefail`, and as the entrypoint.
SHELL ["/bin/bash", "-e", "-o", "pipefail", "-c"]
ENTRYPOINT ["/bin/bash"]
# Copy /nix/store and the env symlink tree
COPY --from=builder /tmp/nix-store-closure /nix/store
COPY --from=builder /tmp/build/result /nix/ci-env
ENV PATH="/nix/ci-env/bin:$PATH"
RUN <<EOF
ccache --version
clang-format --version
cmake --version
conan --version
g++ --version
gcc --version
gcovr --version
git --version
make --version
mold --version
ninja --version
perl --version
pkg-config --version
pre-commit --version
python3 --version
run-clang-tidy --help
vim --version
EOF

10
flake.lock generated
View File

@@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1777954456,
"narHash": "sha256-hGdgeU2Nk87RAuZyYjyDjFL6LK7dAZN5RE9+hrDTkDU=",
"lastModified": 1780243769,
"narHash": "sha256-x5UQuRsH3MqI0U9afaXSNqzTPSeZlRLvFAav2Ux1pNw=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "549bd84d6279f9852cae6225e372cc67fb91a4c1",
"rev": "331800de5053fcebacf6813adb5db9c9dca22a0c",
"type": "github"
},
"original": {
@@ -15,7 +15,7 @@
"type": "indirect"
}
},
"nixpkgs-glibc231": {
"nixpkgs-custom-glibc": {
"flake": false,
"locked": {
"lastModified": 1593520194,
@@ -35,7 +35,7 @@
"root": {
"inputs": {
"nixpkgs": "nixpkgs",
"nixpkgs-glibc231": "nixpkgs-glibc231"
"nixpkgs-custom-glibc": "nixpkgs-custom-glibc"
}
}
},

View File

@@ -6,16 +6,16 @@
# version — matches the system libc on Ubuntu 20.04 LTS. Imported
# manually (flake = false) because this revision predates nixpkgs'
# own flake.nix.
nixpkgs-glibc231 = {
nixpkgs-custom-glibc = {
url = "github:NixOS/nixpkgs/9cd98386a38891d1074fc18036b842dc4416f562";
flake = false;
};
};
outputs =
{ nixpkgs, nixpkgs-glibc231, ... }:
{ nixpkgs, nixpkgs-custom-glibc, ... }:
let
forEachSystem = import ./nix/utils.nix { inherit nixpkgs nixpkgs-glibc231; };
forEachSystem = import ./nix/utils.nix { inherit nixpkgs nixpkgs-custom-glibc; };
in
{
devShells = forEachSystem (import ./nix/devshell.nix);

View File

@@ -1,139 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2024 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_BASICS_CANPROCESS_H_INCLUDED
#define RIPPLE_BASICS_CANPROCESS_H_INCLUDED
#include <functional>
#include <mutex>
#include <set>
/** RAII class to check if an Item is already being processed on another thread,
* as indicated by it's presence in a Collection.
*
* If the Item is not in the Collection, it will be added under lock in the
* ctor, and removed under lock in the dtor. The object will be considered
* "usable" and evaluate to `true`.
*
* If the Item is in the Collection, no changes will be made to the collection,
* and the CanProcess object will be considered "unusable".
*
* It's up to the caller to decide what "usable" and "unusable" mean. (e.g.
* Process or skip a block of code, or set a flag.)
*
* The current use is to avoid lock contention that would be involved in
* processing something associated with the Item.
*
* Examples:
*
* void IncomingLedgers::acquireAsync(LedgerHash const& hash, ...)
* {
* if (CanProcess check{acquiresMutex_, pendingAcquires_, hash})
* {
* acquire(hash, ...);
* }
* }
*
* bool
* NetworkOPsImp::recvValidation(
* std::shared_ptr<STValidation> const& val,
* std::string const& source)
* {
* CanProcess check(
* validationsMutex_, pendingValidations_, val->getLedgerHash());
* BypassAccept bypassAccept =
* check ? BypassAccept::no : BypassAccept::yes;
* handleNewValidation(app_, val, source, bypassAccept, m_journal);
* }
*
*/
class CanProcess
{
public:
template <class Mutex, class Collection, class Item>
CanProcess(Mutex& mtx, Collection& collection, Item const& item)
: cleanup_(insert(mtx, collection, item))
{
}
~CanProcess()
{
if (cleanup_)
cleanup_();
}
CanProcess(CanProcess const&) = delete;
CanProcess&
operator=(CanProcess const&) = delete;
explicit
operator bool() const
{
return static_cast<bool>(cleanup_);
}
private:
template <bool useIterator, class Mutex, class Collection, class Item>
std::function<void()>
doInsert(Mutex& mtx, Collection& collection, Item const& item)
{
std::unique_lock<Mutex> lock(mtx);
// TODO: Use structured binding once LLVM 16 is the minimum supported
// version. See also: https://github.com/llvm/llvm-project/issues/48582
// https://github.com/llvm/llvm-project/commit/127bf44385424891eb04cff8e52d3f157fc2cb7c
auto const insertResult = collection.insert(item);
auto const it = insertResult.first;
if (!insertResult.second)
return {};
if constexpr (useIterator)
return [&, it]() {
std::unique_lock<Mutex> lock(mtx);
collection.erase(it);
};
else
return [&]() {
std::unique_lock<Mutex> lock(mtx);
collection.erase(item);
};
}
// Generic insert() function doesn't use iterators because they may get
// invalidated
template <class Mutex, class Collection, class Item>
std::function<void()>
insert(Mutex& mtx, Collection& collection, Item const& item)
{
return doInsert<false>(mtx, collection, item);
}
// Specialize insert() for std::set, which does not invalidate iterators for
// insert and erase
template <class Mutex, class Item>
std::function<void()>
insert(Mutex& mtx, std::set<Item>& collection, Item const& item)
{
return doInsert<true>(mtx, collection, item);
}
// If set, then the item is "usable"
std::function<void()> cleanup_;
};
#endif

View File

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

View File

@@ -2,12 +2,16 @@
#include <xrpl/beast/utility/instrumentation.h>
#include <array>
#include <cstdint>
#include <functional>
#include <limits>
#include <optional>
#include <ostream>
#include <set>
#include <stdexcept>
#include <string>
#include <unordered_map>
namespace xrpl {
@@ -38,17 +42,64 @@ isPowerOfTen(T value)
return logTen(value).has_value();
}
namespace detail {
/** Builds a table of the powers of 10
*
* This function is marked consteval, so it can only be run in
* a constexpr context. This assures that it is and can only be run at
* compile time. Doing it at runtime would be pretty wasteful and
* inefficient.
*/
constexpr std::size_t kUint64Digits = 20;
constexpr std::size_t kUint128Digits = 39;
template <typename T, std::size_t Digits>
consteval std::array<T, Digits>
buildPowersOfTen()
{
std::array<T, Digits> result{};
T power = 1;
std::size_t exponent = 0;
// end the loop early so it doesn't overflow;
for (; exponent < result.size() - 1; ++exponent, power *= 10)
{
result[exponent] = power;
if (power > std::numeric_limits<T>::max() / 10)
throw std::logic_error("Power of 10 table is too big");
}
result[exponent] = power;
if (power < std::numeric_limits<T>::max() / 10)
throw std::logic_error("Power of 10 table is not big enough for the given type");
return result;
}
} // namespace detail
template <typename T = std::uint64_t, std::size_t Digits = detail::kUint64Digits>
constexpr std::array<T, Digits> kPowerOfTenImpl = detail::buildPowersOfTen<T, Digits>();
constexpr auto kPowerOfTen = kPowerOfTenImpl<std::uint64_t, detail::kUint64Digits>;
static_assert(kPowerOfTen[0] == 1);
static_assert(kPowerOfTen[1] == 10);
static_assert(kPowerOfTen[10] == 10'000'000'000);
static_assert(
isPowerOfTen(kPowerOfTen.back()) && *logTen(kPowerOfTen.back()) == detail::kUint64Digits - 1);
/** MantissaRange defines a range for the mantissa of a normalized Number.
*
* The mantissa is in the range [min, max], where
* * min is a power of 10, and
* * max = min * 10 - 1.
*
* The mantissa_scale enum indicates whether the range is "small" or "large".
* This intentionally restricts the number of MantissaRanges that can be
* instantiated to two: one for each scale.
* The MantissaScale enum indicates properties of the range: size, and some behavioral
* options. This intentionally restricts the number of unique MantissaRanges that can
* be instantiated: one for each scale.
*
* The "small" scale is based on the behavior of STAmount for IOUs. It has a min
* The "Small" scale is based on the behavior of STAmount for IOUs. It has a min
* value of 10^15, and a max value of 10^16-1. This was sufficient for
* uses before Lending Protocol was implemented, mostly related to AMM.
*
@@ -59,46 +110,106 @@ isPowerOfTen(T value)
* STNumber field type, and for internal calculations. That necessitated the
* "large" scale.
*
* The "large" scale is intended to represent all values that can be represented
* The "Large" scales are intended to represent all values that can be represented
* by an STAmount - IOUs, XRP, and MPTs. It has a min value of 10^18, and a max
* value of 10^19-1.
* value of 10^19-1. "LargeLegacy" is like "Large", but preserves
* a rounding error when a computation results in a mantissa of
* Number::kMaxRep that needs to be rounded up, but rounds down
* instead. It will maintain consistent behavior until the fixCleanup3_2_0
* amendment is enabled.
*
* Note that if the mentioned amendments are eventually retired, this class
* should be left in place, but the "small" scale option should be removed. This
* should be left in place, but the "Small" scale option should be removed. This
* will allow for future expansion beyond 64-bits if it is ever needed.
*/
struct MantissaRange
struct MantissaRange final
{
using rep = std::uint64_t;
enum class MantissaScale { Small, Large };
explicit constexpr MantissaRange(MantissaScale scale)
: min(getMin(scale)), log(logTen(min).value_or(-1)), scale(scale)
enum class MantissaScale {
Small,
// LargeLegacy can be removed when fixCleanup3_2_0 is retired
LargeLegacy,
// Large320 can be removed when fixCleanup3_3_0 is retired
Large320,
Large330,
};
// This entire enum can be removed when fixCleanup3_2_0 is retired
enum class CuspRoundingFix : std::uint8_t {
Disabled = 0,
Enabled320 = 1,
Enabled330 = 2,
};
explicit constexpr MantissaRange(MantissaScale sc) : scale(sc)
{
}
rep min;
rep max{(min * 10) - 1};
int log;
MantissaScale scale;
MantissaScale const scale;
int const log{getExponent(scale)};
rep const min{getMin(scale, log)};
rep const max{(min * 10) - 1};
CuspRoundingFix const cuspRoundingFix{isCuspFixEnabled(scale)};
static MantissaRange const&
getMantissaRange(MantissaScale scale);
static std::set<MantissaScale> const&
getAllScales();
private:
static constexpr rep
getMin(MantissaScale scale)
static constexpr int
getExponent(MantissaScale scale)
{
switch (scale)
{
case MantissaScale::Small:
return 1'000'000'000'000'000ULL;
case MantissaScale::Large:
return 1'000'000'000'000'000'000ULL;
return 15;
case MantissaScale::LargeLegacy:
case MantissaScale::Large320:
case MantissaScale::Large330:
return 18;
// LCOV_EXCL_START
default:
// Since this can never be called outside a non-constexpr
// context, this throw assures that the build fails if an
// If called in a constexpr context, this throw assures that the build fails if an
// invalid scale is used.
throw std::runtime_error("Unknown mantissa scale");
// LCOV_EXCL_STOP
}
}
// Keep this function for future use with different ways to compute
// the ranges.
static constexpr rep
getMin(MantissaScale scale, int exponent)
{
if (exponent < 0 || exponent >= kPowerOfTen.size())
throw std::runtime_error("Invalid exponent"); // LCOV_EXCL_LINE
return kPowerOfTen[exponent];
}
static constexpr CuspRoundingFix
isCuspFixEnabled(MantissaScale scale)
{
switch (scale)
{
case MantissaScale::Small:
case MantissaScale::LargeLegacy:
return CuspRoundingFix::Disabled;
case MantissaScale::Large320:
return CuspRoundingFix::Enabled320;
case MantissaScale::Large330:
return CuspRoundingFix::Enabled330;
default:
// If called in a constexpr context, this throw assures that the build fails if an
// invalid scale is used.
throw std::runtime_error("Unknown mantissa scale"); // LCOV_EXCL_LINE
}
}
static std::unordered_map<MantissaScale, MantissaRange> const&
getRanges();
};
// Like std::integral, but only 64-bit integral types.
@@ -203,7 +314,7 @@ concept Integral64 = std::is_same_v<T, std::int64_t> || std::is_same_v<T, std::u
* amendments are enabled to determine which result to expect.
*
*/
class Number
class Number final
{
using rep = std::int64_t;
using internalrep = MantissaRange::rep;
@@ -220,6 +331,8 @@ public:
static constexpr internalrep kMaxRep = std::numeric_limits<rep>::max();
static_assert(kMaxRep == 9'223'372'036'854'775'807);
static_assert(-kMaxRep == std::numeric_limits<rep>::min() + 1);
static constexpr internalrep kMaxRepUp = ((kMaxRep / 10) + 1) * 10;
static_assert(kMaxRepUp == 9'223'372'036'854'775'810ULL);
// May need to make unchecked private
struct Unchecked
@@ -309,33 +422,40 @@ public:
}
friend constexpr bool
operator<(Number const& x, Number const& y) noexcept
operator<(Number const& l, Number const& r) noexcept
{
bool const lneg = l.negative_;
bool const rneg = r.negative_;
// If the two amounts have different signs (zero is treated as positive)
// then the comparison is true iff the left is negative.
bool const lneg = x.negative_;
bool const rneg = y.negative_;
if (lneg != rneg)
return lneg;
// Both have same sign and the left is zero: the right must be
// greater than 0.
if (x.mantissa_ == 0)
return y.mantissa_ > 0;
// Both have same sign and the left is zero: both must be non-negative.
// If the right is greater than 0, then it is larger, so the comparison is true.
if (l.mantissa_ == 0)
return r.mantissa_ > 0;
// Both have same sign, the right is zero and the left is non-zero.
if (y.mantissa_ == 0)
// Both have same sign, the right is zero and the left is non-zero, so the left must be
// positive, and thus is larger, so the comparison is false.
if (r.mantissa_ == 0)
return false;
// Both have the same sign, compare by exponents:
if (x.exponent_ > y.exponent_)
if (l.exponent_ > r.exponent_)
return lneg;
if (x.exponent_ < y.exponent_)
if (l.exponent_ < r.exponent_)
return !lneg;
// If equal exponents, compare mantissas
return x.mantissa_ < y.mantissa_;
// If equal signs and exponents, compare mantissas.
if (lneg)
{
// If negative, the operator is reversed.
return l.mantissa_ > r.mantissa_;
}
return l.mantissa_ < r.mantissa_;
}
/** Return the sign of the amount */
@@ -424,49 +544,34 @@ public:
return kRange.get().log;
}
/// oneSmall is needed because the ranges are private
static constexpr Number
oneSmall();
/// oneLarge is needed because the ranges are private
static constexpr Number
oneLarge();
// And one is needed because it needs to choose between oneSmall and
// oneLarge based on the current range
static Number
one();
template <Integral64 T>
template <
auto MinMantissa,
auto MaxMantissa,
Integral64 T = std::decay_t<decltype(MinMantissa)>>
[[nodiscard]]
std::pair<T, int>
normalizeToRange(T minMantissa, T maxMantissa) const;
normalizeToRange() const;
private:
static thread_local RoundingMode mode;
// The available ranges for mantissa
static constexpr MantissaRange kSmallRange{MantissaRange::MantissaScale::Small};
static_assert(isPowerOfTen(kSmallRange.min));
static_assert(kSmallRange.min == 1'000'000'000'000'000LL);
static_assert(kSmallRange.max == 9'999'999'999'999'999LL);
static_assert(kSmallRange.log == 15);
static_assert(kSmallRange.min < kMaxRep);
static_assert(kSmallRange.max < kMaxRep);
static constexpr MantissaRange kLargeRange{MantissaRange::MantissaScale::Large};
static_assert(isPowerOfTen(kLargeRange.min));
static_assert(kLargeRange.min == 1'000'000'000'000'000'000ULL);
static_assert(kLargeRange.max == internalrep(9'999'999'999'999'999'999ULL));
static_assert(kLargeRange.log == 18);
static_assert(kLargeRange.min < kMaxRep);
static_assert(kLargeRange.max > kMaxRep);
// The range for the mantissa when normalized.
// Use reference_wrapper to avoid making copies, and prevent accidentally
// changing the values inside the range.
static thread_local std::reference_wrapper<MantissaRange const> kRange;
class Guard;
void
normalize();
normalize(MantissaRange const& range);
// Guard has the fields that we need, as well as MantissaRange, so if we have a guard, use that
void
normalize(Guard const& guard);
/** Normalize Number components to an arbitrary range.
*
@@ -481,7 +586,8 @@ private:
T& mantissa,
int& exponent,
internalrep const& minMantissa,
internalrep const& maxMantissa);
internalrep const& maxMantissa,
MantissaRange::CuspRoundingFix cuspRoundingFix);
template <class T>
friend void
@@ -490,7 +596,9 @@ private:
T& mantissa,
int& exponent,
MantissaRange::rep const& minMantissa,
MantissaRange::rep const& maxMantissa);
MantissaRange::rep const& maxMantissa,
MantissaRange::CuspRoundingFix cuspRoundingFix,
bool dropped);
[[nodiscard]] bool
isnormal() const noexcept;
@@ -507,8 +615,6 @@ private:
// UB, and can vary across compilers.
static internalrep
externalToInternal(rep mantissa);
class Guard;
};
constexpr Number::Number(bool negative, internalrep mantissa, int exponent, Unchecked) noexcept
@@ -526,7 +632,7 @@ static constexpr Number kNumZero{};
inline Number::Number(bool negative, internalrep mantissa, int exponent, Normalized)
: Number(negative, mantissa, exponent, Unchecked{})
{
normalize();
normalize(kRange);
}
inline Number::Number(internalrep mantissa, int exponent, Normalized)
@@ -696,10 +802,21 @@ Number::isnormal() const noexcept
kMinExponent <= exponent_ && exponent_ <= kMaxExponent);
}
template <Integral64 T>
template <auto MinMantissa, auto MaxMantissa, Integral64 T>
std::pair<T, int>
Number::normalizeToRange(T minMantissa, T maxMantissa) const
Number::normalizeToRange() const
{
static_assert(std::is_same_v<T, std::uint64_t> || std::is_same_v<T, std::int64_t>);
static_assert(std::is_same_v<T, std::decay_t<decltype(MinMantissa)>>);
static_assert(std::is_same_v<T, std::decay_t<decltype(MaxMantissa)>>);
auto constexpr kMIN = static_cast<T>(MinMantissa);
auto constexpr kMAX = static_cast<T>(MaxMantissa);
static_assert(kMIN > 0);
static_assert(kMIN % 10 == 0);
static_assert(isPowerOfTen(kMIN));
static_assert(kMAX % 10 == 9);
static_assert((kMAX + 1) / 10 == kMIN);
bool negative = negative_;
internalrep mantissa = mantissa_;
int exponent = exponent_;
@@ -711,7 +828,10 @@ Number::normalizeToRange(T minMantissa, T maxMantissa) const
"xrpl::Number::normalizeToRange",
"Number is non-negative for unsigned range.");
}
Number::normalize(negative, mantissa, exponent, minMantissa, maxMantissa);
// Don't need to worry about the cuspRounding fix because rounding up will never take the
// mantissa over maxMantissa with a ones digit value other than 0. 0 can safely be truncated.
Number::normalize(
negative, mantissa, exponent, kMIN, kMAX, MantissaRange::CuspRoundingFix::Disabled);
auto const sign = negative ? -1 : 1;
return std::make_pair(static_cast<T>(sign * mantissa), exponent);
@@ -756,19 +876,11 @@ squelch(Number const& x, Number const& limit) noexcept
return x;
}
inline std::string
to_string(MantissaRange::MantissaScale const& scale)
{
switch (scale)
{
case MantissaRange::MantissaScale::Small:
return "small";
case MantissaRange::MantissaScale::Large:
return "large";
default:
throw std::runtime_error("Bad scale");
}
}
std::string
to_string(MantissaRange::MantissaScale const& scale);
std::string
to_string(Number::RoundingMode const& round);
class SaveNumberRoundMode
{

View File

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

View File

@@ -157,7 +157,7 @@ public:
/** Fetch an item from the cache.
If the digest was not found, Handler
will be called with this signature:
std::shared_ptr<SLE const>(void)
SLE::const_pointer(void)
*/
template <class Handler>
SharedPointerType
@@ -181,14 +181,14 @@ private:
beast::insight::Collector::ptr const& collector)
: hook(collector->makeHook(handler))
, size(collector->makeGauge(prefix, "size"))
, hit_rate(collector->makeGauge(prefix, "hit_rate"))
, hitRate(collector->makeGauge(prefix, "hit_rate"))
{
}
beast::insight::Hook hook;
beast::insight::Gauge size;
beast::insight::Gauge hit_rate;
beast::insight::Gauge hitRate;
std::size_t hits{0};
std::size_t misses{0};
@@ -197,16 +197,16 @@ private:
class KeyOnlyEntry
{
public:
clock_type::time_point last_access;
clock_type::time_point lastAccess;
explicit KeyOnlyEntry(clock_type::time_point const& lastAccess) : last_access(lastAccess)
explicit KeyOnlyEntry(clock_type::time_point const& lastAccess) : lastAccess(lastAccess)
{
}
void
touch(clock_type::time_point const& now)
{
last_access = now;
lastAccess = now;
}
};
@@ -214,10 +214,10 @@ private:
{
public:
shared_weak_combo_pointer_type ptr;
clock_type::time_point last_access;
clock_type::time_point lastAccess;
ValueEntry(clock_type::time_point const& lastAccess, shared_pointer_type const& ptr)
: ptr(ptr), last_access(lastAccess)
: ptr(ptr), lastAccess(lastAccess)
{
}
@@ -246,7 +246,7 @@ private:
void
touch(clock_type::time_point const& now)
{
last_access = now;
lastAccess = now;
}
};
@@ -286,13 +286,13 @@ private:
std::string name_;
// Desired number of cache entries (0 = ignore)
int const target_size_;
int const targetSize_;
// Desired maximum cache age
clock_type::duration const target_age_;
clock_type::duration const targetAge_;
// Number of items cached
int cache_count_{0};
int cacheCount_{0};
cache_type cache_; // Hold strong reference to recent objects
std::uint64_t hits_{0};
std::uint64_t misses_{0};

View File

@@ -34,8 +34,8 @@ inline TaggedCache<
, clock_(clock)
, stats_(name, std::bind(&TaggedCache::collectMetrics, this), collector)
, name_(name)
, target_size_(size)
, target_age_(expiration)
, targetSize_(size)
, targetAge_(expiration)
{
}
@@ -86,7 +86,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
getCacheSize() const
{
std::scoped_lock const lock(mutex_);
return cache_count_;
return cacheCount_;
}
template <
@@ -139,7 +139,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
{
std::scoped_lock const lock(mutex_);
cache_.clear();
cache_count_ = 0;
cacheCount_ = 0;
}
template <
@@ -157,7 +157,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
{
std::scoped_lock const lock(mutex_);
cache_.clear();
cache_count_ = 0;
cacheCount_ = 0;
hits_ = 0;
misses_ = 0;
}
@@ -213,21 +213,21 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
{
std::scoped_lock const lock(mutex_);
if (target_size_ == 0 || (static_cast<int>(cache_.size()) <= target_size_))
if (targetSize_ == 0 || (static_cast<int>(cache_.size()) <= targetSize_))
{
whenExpire = now - target_age_;
whenExpire = now - targetAge_;
}
else
{
whenExpire = now - (target_age_ * target_size_ / cache_.size());
whenExpire = now - (targetAge_ * targetSize_ / cache_.size());
clock_type::duration const minimumAge(std::chrono::seconds(1));
if (whenExpire > (now - minimumAge))
whenExpire = now - minimumAge;
JLOG(journal_.trace())
<< name_ << " is growing fast " << cache_.size() << " of " << target_size_
<< " aging at " << (now - whenExpire).count() << " of " << target_age_.count();
<< name_ << " is growing fast " << cache_.size() << " of " << targetSize_
<< " aging at " << (now - whenExpire).count() << " of " << targetAge_.count();
}
std::vector<std::thread> workers;
@@ -242,7 +242,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
for (std::thread& worker : workers)
worker.join();
cache_count_ -= allRemovals;
cacheCount_ -= allRemovals;
}
// At this point allStuffToSweep will go out of scope outside the lock
// and decrement the reference count on each strong pointer.
@@ -280,7 +280,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
if (entry.isCached())
{
--cache_count_;
--cacheCount_;
entry.ptr.convertToWeak();
ret = true;
}
@@ -317,7 +317,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
std::piecewise_construct,
std::forward_as_tuple(key),
std::forward_as_tuple(clock_.now(), data));
++cache_count_;
++cacheCount_;
return false;
}
@@ -366,12 +366,12 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
data = cachedData;
}
++cache_count_;
++cacheCount_;
return true;
}
entry.ptr = data;
++cache_count_;
++cacheCount_;
return false;
}
@@ -477,7 +477,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
auto [it, inserted] = cache_.emplace(
std::piecewise_construct, std::forward_as_tuple(key), std::forward_as_tuple(now));
if (!inserted)
it->second.last_access = now;
it->second.lastAccess = now;
return inserted;
}
@@ -626,7 +626,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
if (entry.isCached())
{
// independent of cache size, so not counted as a hit
++cache_count_;
++cacheCount_;
entry.touch(clock_.now());
return entry.ptr.getStrong();
}
@@ -658,7 +658,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
if (total != 0)
hitRate = (hits_ * 100) / total;
}
stats_.hit_rate.set(hitRate);
stats_.hitRate.set(hitRate);
}
}
@@ -706,7 +706,7 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
++cit;
}
}
else if (cit->second.last_access <= whenExpire)
else if (cit->second.lastAccess <= whenExpire)
{
// strong, expired
++cacheRemovals;
@@ -773,12 +773,12 @@ TaggedCache<Key, T, IsKeyCache, SharedWeakUnionPointer, SharedPointerType, Hash,
auto cit = partition.begin();
while (cit != partition.end())
{
if (cit->second.last_access > now)
if (cit->second.lastAccess > now)
{
cit->second.last_access = now;
cit->second.lastAccess = now;
++cit;
}
else if (cit->second.last_access <= whenExpire)
else if (cit->second.lastAccess <= whenExpire)
{
cit = partition.erase(cit);
}

View File

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

View File

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

View File

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

View File

@@ -24,20 +24,20 @@ namespace xrpl {
template <class EF>
class ScopeExit
{
EF exit_function_;
bool execute_on_destruction_{true};
EF exitFunction_;
bool executeOnDestruction_{true};
public:
~ScopeExit()
{
if (execute_on_destruction_)
exit_function_();
if (executeOnDestruction_)
exitFunction_();
}
ScopeExit(ScopeExit&& rhs) noexcept(
std::is_nothrow_move_constructible_v<EF> || std::is_nothrow_copy_constructible_v<EF>)
: exit_function_{std::forward<EF>(rhs.exit_function_)}
, execute_on_destruction_{rhs.execute_on_destruction_}
: exitFunction_{std::forward<EF>(rhs.exitFunction_)}
, executeOnDestruction_{rhs.executeOnDestruction_}
{
rhs.release();
}
@@ -51,7 +51,7 @@ public:
std::enable_if_t<
!std::is_same_v<std::remove_cv_t<EFP>, ScopeExit> &&
std::is_constructible_v<EF, EFP>>* = 0) noexcept
: exit_function_{std::forward<EFP>(f)}
: exitFunction_{std::forward<EFP>(f)}
{
static_assert(std::is_nothrow_constructible_v<EF, decltype(std::forward<EFP>(f))>);
}
@@ -59,7 +59,7 @@ public:
void
release() noexcept
{
execute_on_destruction_ = false;
executeOnDestruction_ = false;
}
};
@@ -69,22 +69,22 @@ ScopeExit(EF) -> ScopeExit<EF>;
template <class EF>
class ScopeFail
{
EF exit_function_;
bool execute_on_destruction_{true};
int uncaught_on_creation_{std::uncaught_exceptions()};
EF exitFunction_;
bool executeOnDestruction_{true};
int uncaughtOnCreation_{std::uncaught_exceptions()};
public:
~ScopeFail()
{
if (execute_on_destruction_ && std::uncaught_exceptions() > uncaught_on_creation_)
exit_function_();
if (executeOnDestruction_ && std::uncaught_exceptions() > uncaughtOnCreation_)
exitFunction_();
}
ScopeFail(ScopeFail&& rhs) noexcept(
std::is_nothrow_move_constructible_v<EF> || std::is_nothrow_copy_constructible_v<EF>)
: exit_function_{std::forward<EF>(rhs.exit_function_)}
, execute_on_destruction_{rhs.execute_on_destruction_}
, uncaught_on_creation_{rhs.uncaught_on_creation_}
: exitFunction_{std::forward<EF>(rhs.exitFunction_)}
, executeOnDestruction_{rhs.executeOnDestruction_}
, uncaughtOnCreation_{rhs.uncaughtOnCreation_}
{
rhs.release();
}
@@ -98,7 +98,7 @@ public:
std::enable_if_t<
!std::is_same_v<std::remove_cv_t<EFP>, ScopeFail> &&
std::is_constructible_v<EF, EFP>>* = 0) noexcept
: exit_function_{std::forward<EFP>(f)}
: exitFunction_{std::forward<EFP>(f)}
{
static_assert(std::is_nothrow_constructible_v<EF, decltype(std::forward<EFP>(f))>);
}
@@ -106,7 +106,7 @@ public:
void
release() noexcept
{
execute_on_destruction_ = false;
executeOnDestruction_ = false;
}
};
@@ -116,22 +116,22 @@ ScopeFail(EF) -> ScopeFail<EF>;
template <class EF>
class ScopeSuccess
{
EF exit_function_;
bool execute_on_destruction_{true};
int uncaught_on_creation_{std::uncaught_exceptions()};
EF exitFunction_;
bool executeOnDestruction_{true};
int uncaughtOnCreation_{std::uncaught_exceptions()};
public:
~ScopeSuccess() noexcept(noexcept(exit_function_()))
~ScopeSuccess() noexcept(noexcept(exitFunction_()))
{
if (execute_on_destruction_ && std::uncaught_exceptions() <= uncaught_on_creation_)
exit_function_();
if (executeOnDestruction_ && std::uncaught_exceptions() <= uncaughtOnCreation_)
exitFunction_();
}
ScopeSuccess(ScopeSuccess&& rhs) noexcept(
std::is_nothrow_move_constructible_v<EF> || std::is_nothrow_copy_constructible_v<EF>)
: exit_function_{std::forward<EF>(rhs.exit_function_)}
, execute_on_destruction_{rhs.execute_on_destruction_}
, uncaught_on_creation_{rhs.uncaught_on_creation_}
: exitFunction_{std::forward<EF>(rhs.exitFunction_)}
, executeOnDestruction_{rhs.executeOnDestruction_}
, uncaughtOnCreation_{rhs.uncaughtOnCreation_}
{
rhs.release();
}
@@ -146,14 +146,14 @@ public:
!std::is_same_v<std::remove_cv_t<EFP>, ScopeSuccess> &&
std::is_constructible_v<EF, EFP>>* =
0) noexcept(std::is_nothrow_constructible_v<EF, EFP> || std::is_nothrow_constructible_v<EF, EFP&>)
: exit_function_{std::forward<EFP>(f)}
: exitFunction_{std::forward<EFP>(f)}
{
}
void
release() noexcept
{
execute_on_destruction_ = false;
executeOnDestruction_ = false;
}
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -77,8 +77,8 @@ private:
std::ostream& os_;
Results results_;
SuiteResults suite_results_;
CaseResults case_results_;
SuiteResults suiteResults_;
CaseResults caseResults_;
public:
Reporter(Reporter const&) = delete;
@@ -196,22 +196,22 @@ template <class Unused>
void
Reporter<Unused>::onSuiteBegin(SuiteInfo const& info)
{
suite_results_ = SuiteResults{info.fullName()};
suiteResults_ = SuiteResults{info.fullName()};
}
template <class Unused>
void
Reporter<Unused>::onSuiteEnd()
{
results_.add(suite_results_);
results_.add(suiteResults_);
}
template <class Unused>
void
Reporter<Unused>::onCaseBegin(std::string const& name)
{
case_results_ = CaseResults(name);
os_ << suite_results_.name << (case_results_.name.empty() ? "" : (" " + case_results_.name))
caseResults_ = CaseResults(name);
os_ << suiteResults_.name << (caseResults_.name.empty() ? "" : (" " + caseResults_.name))
<< std::endl;
}
@@ -219,23 +219,23 @@ template <class Unused>
void
Reporter<Unused>::onCaseEnd()
{
suite_results_.add(case_results_);
suiteResults_.add(caseResults_);
}
template <class Unused>
void
Reporter<Unused>::onPass()
{
++case_results_.total;
++caseResults_.total;
}
template <class Unused>
void
Reporter<Unused>::onFail(std::string const& reason)
{
++case_results_.failed;
++case_results_.total;
os_ << "#" << case_results_.total << " failed" << (reason.empty() ? "" : ": ") << reason
++caseResults_.failed;
++caseResults_.total;
os_ << "#" << caseResults_.total << " failed" << (reason.empty() ? "" : ": ") << reason
<< std::endl;
}

View File

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

View File

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

View File

@@ -47,7 +47,7 @@ inline bool
JobQueue::Coro::post()
{
{
std::scoped_lock const lk(mutex_run_);
std::scoped_lock const lk(mutexRun_);
running_ = true;
}
@@ -58,7 +58,7 @@ JobQueue::Coro::post()
}
// The coroutine will not run. Clean up running_.
std::scoped_lock const lk(mutex_run_);
std::scoped_lock const lk(mutexRun_);
running_ = false;
cv_.notify_all();
return false;
@@ -68,7 +68,7 @@ inline void
JobQueue::Coro::resume()
{
{
std::scoped_lock const lk(mutex_run_);
std::scoped_lock const lk(mutexRun_);
running_ = true;
}
{
@@ -92,7 +92,7 @@ JobQueue::Coro::resume()
}
detail::getLocalValues().release();
detail::getLocalValues().reset(saved);
std::scoped_lock const lk(mutex_run_);
std::scoped_lock const lk(mutexRun_);
running_ = false;
cv_.notify_all();
}
@@ -127,7 +127,7 @@ JobQueue::Coro::expectEarlyExit()
inline void
JobQueue::Coro::join()
{
std::unique_lock<std::mutex> lk(mutex_run_);
std::unique_lock<std::mutex> lk(mutexRun_);
cv_.wait(lk, [this]() { return !running_; });
}

View File

@@ -197,7 +197,7 @@ public:
/** Add a suppression peer and get message's relay status.
* Return pair:
* element 1: true if the key is added.
* element 1: true if the peer is added.
* element 2: optional is seated to the relay time point or
* is unseated if has not relayed yet. */
std::pair<bool, std::optional<Stopwatch::time_point>>

View File

@@ -127,7 +127,7 @@ private:
std::function<void()> job_;
std::shared_ptr<LoadEvent> loadEvent_;
std::string name_;
clock_type::time_point queue_time_;
clock_type::time_point queueTime_;
};
using JobCounter = ClosureCounter<void>;

View File

@@ -52,7 +52,7 @@ public:
std::string name_;
bool running_{false};
std::mutex mutex_;
std::mutex mutex_run_;
std::mutex mutexRun_;
std::condition_variable cv_;
boost::coroutines2::coroutine<void>::push_type* yield_{};
boost::coroutines2::coroutine<void>::pull_type coro_;
@@ -246,7 +246,7 @@ private:
// Statistics tracking
perf::PerfLog& perfLog_;
beast::insight::Collector::ptr collector_;
beast::insight::Gauge job_count_;
beast::insight::Gauge jobCount_;
beast::insight::Hook hook_;
std::condition_variable cv_;

View File

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

View File

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

View File

@@ -161,7 +161,7 @@ public:
* While the JSON spec doesn't explicitly disallow this, you should avoid
* calling this method twice with the same tag for the same object.
*
* If CHECK_JSON_WRITER is defined, this function throws an exception if if
* If CHECK_JSON_WRITER is defined, this function throws an exception if
* the tag you use has already been used in this object.
*/
template <typename Type>

View File

@@ -123,7 +123,7 @@ private:
bool preserveOrder,
Keylet const& directory,
uint256 const& key,
std::function<void(std::shared_ptr<SLE> const&)> const& describe);
std::function<void(SLE::ref)> const& describe);
public:
ApplyView() = default;
@@ -153,7 +153,7 @@ public:
@return `nullptr` if the key is not present
*/
virtual std::shared_ptr<SLE>
virtual SLE::pointer
peek(Keylet const& k) = 0;
/** Remove a peeked SLE.
@@ -168,7 +168,7 @@ public:
The key is no longer associated with the SLE.
*/
virtual void
erase(std::shared_ptr<SLE> const& sle) = 0;
erase(SLE::ref sle) = 0;
/** Insert a new state SLE
@@ -189,7 +189,7 @@ public:
@note The key is taken from the SLE
*/
virtual void
insert(std::shared_ptr<SLE> const& sle) = 0;
insert(SLE::ref sle) = 0;
/** Indicate changes to a peeked SLE
@@ -208,7 +208,7 @@ public:
*/
/** @{ */
virtual void
update(std::shared_ptr<SLE> const& sle) = 0;
update(SLE::ref sle) = 0;
//--------------------------------------------------------------------------
@@ -301,7 +301,7 @@ public:
dirAppend(
Keylet const& directory,
Keylet const& key,
std::function<void(std::shared_ptr<SLE> const&)> const& describe)
std::function<void(SLE::ref)> const& describe)
{
if (key.type != ltOFFER)
{
@@ -340,7 +340,7 @@ public:
dirInsert(
Keylet const& directory,
uint256 const& key,
std::function<void(std::shared_ptr<SLE> const&)> const& describe)
std::function<void(SLE::ref)> const& describe)
{
return dirAdd(false, directory, key, describe);
}
@@ -349,7 +349,7 @@ public:
dirInsert(
Keylet const& directory,
Keylet const& key,
std::function<void(std::shared_ptr<SLE> const&)> const& describe)
std::function<void(SLE::ref)> const& describe)
{
return dirAdd(false, directory, key.key, describe);
}
@@ -411,7 +411,7 @@ createRoot(
ApplyView& view,
Keylet const& directory,
uint256 const& key,
std::function<void(std::shared_ptr<SLE> const&)> const& describe);
std::function<void(SLE::ref)> const& describe);
auto
findPreviousPage(ApplyView& view, Keylet const& directory, SLE::ref start);
@@ -434,7 +434,7 @@ insertPage(
SLE::ref next,
uint256 const& key,
Keylet const& directory,
std::function<void(std::shared_ptr<SLE> const&)> const& describe);
std::function<void(SLE::ref)> const& describe);
} // namespace directory
} // namespace xrpl

View File

@@ -67,8 +67,8 @@ public:
std::function<void(
uint256 const& key,
bool isDelete,
std::shared_ptr<SLE const> const& before,
std::shared_ptr<SLE const> const& after)> const& func);
SLE::const_ref before,
SLE::const_ref after)> const& func);
private:
std::optional<STAmount> deliver_;

View File

@@ -9,15 +9,15 @@ class BookDirs
private:
ReadView const* view_ = nullptr;
uint256 const root_;
uint256 const next_quality_;
uint256 const nextQuality_;
uint256 const key_;
std::shared_ptr<SLE const> sle_ = nullptr;
SLE::const_pointer sle_ = nullptr;
unsigned int entry_ = 0;
uint256 index_;
public:
class const_iterator; // NOLINT(readability-identifier-naming)
using value_type = std::shared_ptr<SLE const>;
using value_type = SLE::const_pointer;
BookDirs(ReadView const&, Book const&);
@@ -67,16 +67,16 @@ private:
friend class BookDirs;
const_iterator(ReadView const& view, uint256 const& root, uint256 const& dirKey)
: view_(&view), root_(root), key_(dirKey), cur_key_(dirKey)
: view_(&view), root_(root), key_(dirKey), curKey_(dirKey)
{
}
ReadView const* view_ = nullptr;
uint256 root_;
uint256 next_quality_;
uint256 nextQuality_;
uint256 key_;
uint256 cur_key_;
std::shared_ptr<SLE const> sle_;
uint256 curKey_;
SLE::const_pointer sle_;
unsigned int entry_ = 0;
uint256 index_;
std::optional<value_type> mutable cache_;

View File

@@ -36,7 +36,7 @@ public:
bool
exists(Keylet const& k) const override;
std::shared_ptr<SLE const>
SLE::const_pointer
read(Keylet const& k) const override;
bool

View File

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

View File

@@ -22,12 +22,12 @@ class Dir
private:
ReadView const* view_ = nullptr;
Keylet root_;
std::shared_ptr<SLE const> sle_;
SLE::const_pointer sle_;
STVector256 const* indexes_ = nullptr;
public:
class ConstIterator;
using value_type = std::shared_ptr<SLE const>;
using value_type = SLE::const_pointer;
Dir(ReadView const&, Keylet const&);
@@ -102,7 +102,7 @@ private:
Keylet page_;
uint256 index_;
std::optional<value_type> mutable cache_;
std::shared_ptr<SLE const> sle_;
SLE::const_pointer sle_;
STVector256 const* indexes_ = nullptr;
std::vector<uint256>::const_iterator it_;
};

View File

@@ -166,7 +166,7 @@ public:
std::optional<uint256>
succ(uint256 const& key, std::optional<uint256> const& last = std::nullopt) const override;
std::shared_ptr<SLE const>
SLE::const_pointer
read(Keylet const& k) const override;
std::unique_ptr<SlesType::iter_base>
@@ -202,16 +202,16 @@ public:
//
void
rawErase(std::shared_ptr<SLE> const& sle) override;
rawErase(SLE::ref sle) override;
void
rawInsert(std::shared_ptr<SLE> const& sle) override;
rawInsert(SLE::ref sle) override;
void
rawErase(uint256 const& key);
void
rawReplace(std::shared_ptr<SLE> const& sle) override;
rawReplace(SLE::ref sle) override;
void
rawDestroyXRP(XRPAmount const& fee) override
@@ -361,7 +361,7 @@ public:
bool
isVotingLedger() const;
std::shared_ptr<SLE>
SLE::pointer
peek(Keylet const& k) const;
private:

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