Compare commits

..

22 Commits

Author SHA1 Message Date
Ed Hennis
4304b3acb4 Fix clang-tidy issues 2026-04-17 18:51:07 -04:00
Ed Hennis
29af96bfa1 Address copilot review feedback: correct sign of borrowerDelta 2026-04-17 18:46:50 -04:00
Ed Hennis
7944d03795 Merge remote-tracking branch 'upstream/develop' into ximinez/loanpay-assertion-develop
* upstream/develop: (30 commits)
  chore: Enable clang-tidy include cleaner (6947)
  fix: Change AMMClawback return code to tecNO_PERMISSION (6946)
  ci: [DEPENDABOT] bump actions/upload-pages-artifact from 4.0.0 to 5.0.0 (6927)
  ci: [DEPENDABOT] bump actions/upload-artifact from 7.0.0 to 7.0.1 (6928)
  chore: Enable clang-tidy readability checks (6930)
  fix: Fix unity build for book step (6942)
  chore: Move codegen venv setup into build stage (6617)
  chore: Enable most clang-tidy bugprone checks (6929)
  refactor: Improve exception handling (6540) (6735)
  refactor: Remove unused notTooManyOffers function from NFTokenUtils (6737)
  fix: Change `Tuning::bookOffers` minimum limit to 1 (6812)
  chore: Make pre-commit line ending conversions work on Windows (6832) (6833)
  fix: Add description for `terLOCKED` error (6811)
  fix: Address AI reviewer comments for Permission Delegation (6675)
  refactor: Combine `AMMHelpers` and `AMMUtils` (6733)
  feat: Add MPT support to DEX (5285)
  fix: Handle WSClient write failure when server closes WebSocket (6671)
  ci: Change conditions for uploading artifacts in public/private/org repos (6734)
  refactor: Rename non-functional uses of `ripple(d)` to `xrpl(d)` (6676)
  refactor: Move more helper files into `libxrpl/ledger/helpers` (6731)
  ...
2026-04-17 16:13:26 -04:00
Alex Kremer
653a383ff5 chore: Enable clang-tidy include cleaner (#6947) 2026-04-17 16:43:49 +00:00
Gregory Tsipenyuk
affe5835fe fix: Change AMMClawback return code to tecNO_PERMISSION (#6946) 2026-04-17 14:19:58 +00:00
dependabot[bot]
ef2642f873 ci: [DEPENDABOT] bump actions/upload-pages-artifact from 4.0.0 to 5.0.0 (#6927)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-17 14:02:02 +00:00
dependabot[bot]
b2038163bc ci: [DEPENDABOT] bump actions/upload-artifact from 7.0.0 to 7.0.1 (#6928)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-17 14:01:56 +00:00
Alex Kremer
f1a5ba43ad chore: Enable clang-tidy readability checks (#6930)
Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
2026-04-17 13:30:52 +00:00
Jingchen
4a73be499d fix: Fix unity build for book step (#6942)
Co-authored-by: xrplf-ai-reviewer[bot] <266832837+xrplf-ai-reviewer[bot]@users.noreply.github.com>
2026-04-16 17:12:00 +00:00
Sergey Kuznetsov
d52d735543 chore: Move codegen venv setup into build stage (#6617)
Co-authored-by: JCW <a1q123456@users.noreply.github.com>
Co-authored-by: Bart <bthomee@users.noreply.github.com>
2026-04-15 18:50:49 +00:00
Ed Hennis
b4b47e80ba Merge branch 'develop' into ximinez/loanpay-assertion 2026-04-01 13:39:09 -04:00
Ed Hennis
c8e1d02dee Merge branch 'develop' into ximinez/loanpay-assertion 2026-04-01 11:45:36 -04:00
Ed Hennis
f68b3326df Review feedback from @tapanito
- Return a default value in LoanPay balanceScale if the exponent list is
  empty.
- Amendment gate the "roundedAmount" change in overpayment.
- Improve comments and logging.
documentation
2026-03-31 21:02:28 -04:00
Ed Hennis
da1cb2d7ce Merge remote-tracking branch 'upstream/develop' into ximinez/loanpay-assertion
* upstream/develop: (149 commits)
  fix: Fix previous ledger size typo in RCLConsensus (6696)
  chore: Enable clang-tidy misc checks (6655)
  ci: Use pull_request_target to check for signed commits (6697)
  chore: Remove unnecessary clang-format off/on directives (6682)
  fix: Fix Workers::stop() race between m_allPaused and m_runningTaskCount (6574)
  ci: Only publish docs in public repos (6687)
  chore: Enable remaining clang-tidy `performance` checks (6648)
  refactor: Address PR comments after the modularisation PRs (6389)
  chore: Fix clang-tidy header filter (6686)
  ci: [DEPENDABOT] bump actions/deploy-pages from 4.0.5 to 5.0.0 (6684)
  ci: [DEPENDABOT] bump codecov/codecov-action from 5.5.3 to 6.0.0 (6685)
  fix: Guard Coro::resume() against completed coroutines (6608)
  refactor: Split LoanInvariant into LoanBrokerInvariant and LoanInvariant (6674)
  ci: Don't publish docs on release branches (6673)
  refactor: Make function naming in ServiceRegistry consistent (6390)
  chore: Shorten job names to stay within Linux 15-char thread limit (6669)
  fix: Improve loan invariant message (6668)
  ci: Upload artifacts only in public repositories (6670)
  ci: Add conflicting-pr workflow (6656)
  chore: Add more AI tools to .gitignore (6658)
  ...
2026-03-31 18:54:27 -04:00
Ed Hennis
0797a5d4db Address an outdated TODO comment 2026-03-31 18:53:10 -04:00
Ed Hennis
d33ee7ed46 Merge commit '2c1fad1023' into HEAD
* commit '2c1fad1023':
  chore: Apply clang-format width 100 (6387)
2026-03-31 18:53:02 -04:00
Ed Hennis
53183c71e8 Update formatting 2026-03-31 18:44:32 -04:00
Ed Hennis
05eaef5233 Merge commit '25cca465538a56cce501477f9e5e2c1c7ea2d84c' into HEAD
* commit '25cca465538a56cce501477f9e5e2c1c7ea2d84c': (22 commits)
  chore: Set clang-format width to 100 in config file (6387)
  chore: Set cmake-format width to 100 (6386)
  ci: Add clang tidy workflow to ci (6369)
  refactor: Modularize app/tx (6228)
  refactor: Decouple app/tx from `Application` and `Config` (6227)
  chore: Update clang-format to 21.1.8 (6352)
  refactor: Modularize `HashRouter`, `Conditions`, and `OrderBookDB` (6226)
  chore: Fix minor issues in comments (6346)
  refactor: Modularize the NetworkOPs interface (6225)
  chore: Fix `gcov` lib coverage build failure on macOS (6350)
  refactor: Modularize RelationalDB (6224)
  refactor: Modularize WalletDB and Manifest (6223)
  fix: Update invariant checks for Permissioned Domains (6134)
  refactor: Change main thread name to `xrpld-main` (6336)
  refactor: Fix spelling issues in tests (6199)
  test: Add file and line location to Env (6276)
  chore: Remove CODEOWNERS (6337)
  perf: Remove unnecessary caches (5439)
  chore: Restore unity builds (6328)
  refactor: Update secp256k1 to 0.7.1 (6331)
  ...
2026-03-31 18:42:49 -04:00
Ed Hennis
e44fc46ad0 Verify and log LoanPay fund conservation in all builds
- A warning will be logged if there's a mismatch.
2026-03-31 18:22:16 -04:00
Ed Hennis
3f8f5a081f Review feedback from @tapanito: readability, duplicate checks 2026-03-31 18:22:16 -04:00
Ed Hennis
14236fb767 Fix formatting 2026-02-04 17:26:45 -05:00
Ed Hennis
c0b6712064 Fix touchy "funds are conserved" assertion in LoanPay
- Add "Yield Theft via Rounding Manipulation" test, which used to
  reliably triggered it. The test now verifies that no "yield theft"
  occurs.
2026-02-04 17:18:10 -05:00
896 changed files with 12105 additions and 2709 deletions

View File

@@ -50,20 +50,21 @@ ForEachMacros: [Q_FOREACH, BOOST_FOREACH]
IncludeBlocks: Regroup
IncludeCategories:
- Regex: "^<(test)/"
Priority: 0
- Regex: "^<(xrpld)/"
Priority: 1
- Regex: "^<(xrpl)/"
- Regex: "^<(xrpld)/"
Priority: 2
- Regex: "^<(boost)/"
- Regex: "^<(xrpl)/"
Priority: 3
- Regex: "^.*/"
- Regex: "^<(boost)/"
Priority: 4
- Regex: '^.*\.h'
- Regex: "^.*/"
Priority: 5
- Regex: ".*"
- Regex: '^.*\.h'
Priority: 6
- Regex: ".*"
Priority: 7
IncludeIsMainRegex: "$"
MainIncludeChar: AngleBracket
IndentCaseLabels: true
IndentFunctionDeclarationAfterType: false
IndentRequiresClause: true

View File

@@ -90,6 +90,7 @@ Checks: "-*,
misc-const-correctness,
misc-definitions-in-headers,
misc-header-include-cycle,
misc-include-cleaner,
misc-misplaced-const,
misc-redundant-expression,
misc-static-assert,
@@ -108,37 +109,35 @@ Checks: "-*,
performance-move-constructor-init,
performance-no-automatic-move,
performance-trivially-destructible,
# readability-avoid-nested-conditional-operator, # has issues
# readability-avoid-return-with-void-value, # has issues
# readability-braces-around-statements, # has issues
# readability-const-return-type, # has issues
# readability-container-contains, # has issues
# readability-container-size-empty, # has issues
# readability-convert-member-functions-to-static, # has issues
readability-avoid-nested-conditional-operator,
readability-avoid-return-with-void-value,
readability-braces-around-statements,
readability-const-return-type,
readability-container-contains,
readability-container-size-empty,
readability-convert-member-functions-to-static,
readability-duplicate-include,
# readability-else-after-return, # has issues
# readability-enum-initial-value, # has issues
# readability-implicit-bool-conversion, # has issues
# readability-make-member-function-const, # has issues
# readability-math-missing-parentheses, # has issues
readability-else-after-return,
readability-enum-initial-value,
readability-implicit-bool-conversion,
readability-make-member-function-const,
readability-math-missing-parentheses,
readability-misleading-indentation,
readability-non-const-parameter,
# readability-redundant-casting, # has issues
# readability-redundant-declaration, # has issues
# readability-redundant-inline-specifier, # has issues
# readability-redundant-member-init, # has issues
readability-redundant-casting,
readability-redundant-declaration,
readability-redundant-inline-specifier,
readability-redundant-member-init,
readability-redundant-string-init,
readability-reference-to-constructed-temporary,
# readability-simplify-boolean-expr, # has issues
# readability-static-definition-in-anonymous-namespace, # has issues
# readability-suspicious-call-argument, # has issues
readability-simplify-boolean-expr,
readability-static-definition-in-anonymous-namespace,
readability-suspicious-call-argument,
readability-use-std-min-max
"
# ---
# other checks that have issues that need to be resolved:
#
# misc-include-cleaner,
#
# 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-identifier-naming, # https://github.com/XRPLF/rippled/pull/6571
@@ -194,7 +193,7 @@ CheckOptions:
# readability-identifier-naming.FunctionIgnoredRegexp: ".*tag_invoke.*"
bugprone-unsafe-functions.ReportMoreUnsafeFunctions: true
bugprone-unused-return-value.CheckedReturnTypes: ::std::error_code;::std::error_condition;::std::errc
# misc-include-cleaner.IgnoreHeaders: '.*/(detail|impl)/.*;.*(expected|unexpected).*;.*ranges_lower_bound\.h;time.h;stdlib.h;__chrono/.*;fmt/chrono.h;boost/uuid/uuid_hash.hpp'
misc-include-cleaner.IgnoreHeaders: ".*/(detail|impl)/.*;.*fwd\\.h(pp)?;time.h;stdlib.h;sqlite3.h;netinet/in\\.h;sys/resource\\.h;sys/sysinfo\\.h;linux/sysinfo\\.h;__chrono/.*;bits/.*;_abort\\.h;boost/uuid/uuid_hash.hpp;boost/beast/core/flat_buffer\\.hpp;boost/beast/http/field\\.hpp;boost/beast/http/dynamic_body\\.hpp;boost/beast/http/message\\.hpp;boost/beast/http/read\\.hpp;boost/beast/http/write\\.hpp;openssl/obj_mac\\.h"
#
HeaderFilterRegex: '^.*/(test|xrpl|xrpld)/.*\.(h|hpp)$'
ExcludeHeaderFilterRegex: '^.*/protocol_autogen/.*\.(h|hpp)$'

View File

@@ -2,19 +2,19 @@ Loop: test.jtx test.toplevel
test.toplevel > test.jtx
Loop: test.jtx test.unit_test
test.unit_test == test.jtx
test.unit_test ~= test.jtx
Loop: xrpld.app xrpld.overlay
xrpld.overlay ~= xrpld.app
xrpld.app > xrpld.overlay
Loop: xrpld.app xrpld.peerfinder
xrpld.peerfinder == xrpld.app
xrpld.peerfinder ~= xrpld.app
Loop: xrpld.app xrpld.rpc
xrpld.rpc > xrpld.app
Loop: xrpld.app xrpld.shamap
xrpld.shamap ~= xrpld.app
xrpld.shamap > xrpld.app
Loop: xrpld.overlay xrpld.rpc
xrpld.rpc ~= xrpld.overlay

View File

@@ -3,13 +3,17 @@ libxrpl.conditions > xrpl.basics
libxrpl.conditions > xrpl.conditions
libxrpl.core > xrpl.basics
libxrpl.core > xrpl.core
libxrpl.core > xrpl.json
libxrpl.crypto > xrpl.basics
libxrpl.json > xrpl.basics
libxrpl.json > xrpl.json
libxrpl.ledger > xrpl.basics
libxrpl.ledger > xrpl.json
libxrpl.ledger > xrpl.ledger
libxrpl.ledger > xrpl.nodestore
libxrpl.ledger > xrpl.protocol
libxrpl.ledger > xrpl.server
libxrpl.ledger > xrpl.shamap
libxrpl.net > xrpl.basics
libxrpl.net > xrpl.net
libxrpl.nodestore > xrpl.basics
@@ -19,19 +23,22 @@ libxrpl.nodestore > xrpl.protocol
libxrpl.protocol > xrpl.basics
libxrpl.protocol > xrpl.json
libxrpl.protocol > xrpl.protocol
libxrpl.protocol_autogen > xrpl.protocol_autogen
libxrpl.rdb > xrpl.basics
libxrpl.rdb > xrpl.core
libxrpl.rdb > xrpl.rdb
libxrpl.resource > xrpl.basics
libxrpl.resource > xrpl.json
libxrpl.resource > xrpl.protocol
libxrpl.resource > xrpl.resource
libxrpl.server > xrpl.basics
libxrpl.server > xrpl.core
libxrpl.server > xrpl.json
libxrpl.server > xrpl.protocol
libxrpl.server > xrpl.rdb
libxrpl.server > xrpl.resource
libxrpl.server > xrpl.server
libxrpl.shamap > xrpl.basics
libxrpl.shamap > xrpl.nodestore
libxrpl.shamap > xrpl.protocol
libxrpl.shamap > xrpl.shamap
libxrpl.tx > xrpl.basics
@@ -43,12 +50,11 @@ libxrpl.tx > xrpl.protocol
libxrpl.tx > xrpl.server
libxrpl.tx > xrpl.tx
test.app > test.jtx
test.app > test.rpc
test.app > test.toplevel
test.app > test.unit_test
test.app > xrpl.basics
test.app > xrpl.core
test.app > xrpld.app
test.app > xrpld.consensus
test.app > xrpld.core
test.app > xrpld.overlay
test.app > xrpld.rpc
@@ -56,9 +62,9 @@ test.app > xrpl.json
test.app > xrpl.ledger
test.app > xrpl.nodestore
test.app > xrpl.protocol
test.app > xrpl.rdb
test.app > xrpl.resource
test.app > xrpl.server
test.app > xrpl.shamap
test.app > xrpl.tx
test.basics > test.jtx
test.basics > test.unit_test
@@ -71,16 +77,17 @@ test.beast > xrpl.basics
test.conditions > xrpl.basics
test.conditions > xrpl.conditions
test.consensus > test.csf
test.consensus > test.jtx
test.consensus > test.toplevel
test.consensus > test.unit_test
test.consensus > xrpl.basics
test.consensus > xrpld.app
test.consensus > xrpld.consensus
test.consensus > xrpl.json
test.consensus > xrpl.ledger
test.consensus > xrpl.protocol
test.consensus > xrpl.shamap
test.consensus > xrpl.tx
test.core > test.jtx
test.core > test.toplevel
test.core > test.unit_test
test.core > xrpl.basics
test.core > xrpl.core
@@ -108,27 +115,32 @@ test.jtx > xrpl.resource
test.jtx > xrpl.server
test.jtx > xrpl.tx
test.ledger > test.jtx
test.ledger > test.toplevel
test.ledger > xrpl.basics
test.ledger > xrpl.core
test.ledger > xrpld.app
test.ledger > xrpld.core
test.ledger > xrpl.json
test.ledger > xrpl.ledger
test.ledger > xrpl.protocol
test.nodestore > test.jtx
test.nodestore > test.toplevel
test.nodestore > test.unit_test
test.nodestore > xrpl.basics
test.nodestore > xrpld.core
test.nodestore > xrpl.nodestore
test.nodestore > xrpl.protocol
test.nodestore > xrpl.rdb
test.overlay > test.jtx
test.overlay > test.toplevel
test.overlay > test.unit_test
test.overlay > xrpl.basics
test.overlay > xrpld.app
test.overlay > xrpld.core
test.overlay > xrpld.overlay
test.overlay > xrpld.peerfinder
test.overlay > xrpl.ledger
test.overlay > xrpl.json
test.overlay > xrpl.nodestore
test.overlay > xrpl.protocol
test.overlay > xrpl.resource
test.overlay > xrpl.server
test.overlay > xrpl.shamap
test.peerfinder > test.beast
test.peerfinder > test.unit_test
@@ -136,7 +148,7 @@ test.peerfinder > xrpl.basics
test.peerfinder > xrpld.core
test.peerfinder > xrpld.peerfinder
test.peerfinder > xrpl.protocol
test.protocol > test.toplevel
test.protocol > test.jtx
test.protocol > test.unit_test
test.protocol > xrpl.basics
test.protocol > xrpl.json
@@ -145,7 +157,6 @@ test.resource > test.unit_test
test.resource > xrpl.basics
test.resource > xrpl.resource
test.rpc > test.jtx
test.rpc > test.toplevel
test.rpc > xrpl.basics
test.rpc > xrpl.core
test.rpc > xrpld.app
@@ -159,13 +170,12 @@ test.rpc > xrpl.resource
test.rpc > xrpl.server
test.rpc > xrpl.tx
test.server > test.jtx
test.server > test.toplevel
test.server > test.unit_test
test.server > xrpl.basics
test.server > xrpld.app
test.server > xrpld.core
test.server > xrpld.rpc
test.server > xrpl.json
test.server > xrpl.protocol
test.server > xrpl.server
test.shamap > test.unit_test
test.shamap > xrpl.basics
@@ -239,19 +249,20 @@ xrpld.consensus > xrpl.ledger
xrpld.consensus > xrpl.protocol
xrpld.core > xrpl.basics
xrpld.core > xrpl.core
xrpld.core > xrpl.json
xrpld.core > xrpl.net
xrpld.core > xrpl.protocol
xrpld.core > xrpl.rdb
xrpld.overlay > xrpl.basics
xrpld.overlay > xrpl.core
xrpld.overlay > xrpld.consensus
xrpld.overlay > xrpld.core
xrpld.overlay > xrpld.peerfinder
xrpld.overlay > xrpl.json
xrpld.overlay > xrpl.ledger
xrpld.overlay > xrpl.protocol
xrpld.overlay > xrpl.rdb
xrpld.overlay > xrpl.resource
xrpld.overlay > xrpl.server
xrpld.overlay > xrpl.shamap
xrpld.overlay > xrpl.tx
xrpld.peerfinder > xrpl.basics
xrpld.peerfinder > xrpld.core
@@ -261,6 +272,7 @@ xrpld.perflog > xrpl.basics
xrpld.perflog > xrpl.core
xrpld.perflog > xrpld.rpc
xrpld.perflog > xrpl.json
xrpld.perflog > xrpl.protocol
xrpld.rpc > xrpl.basics
xrpld.rpc > xrpl.core
xrpld.rpc > xrpld.core
@@ -272,5 +284,9 @@ xrpld.rpc > xrpl.protocol
xrpld.rpc > xrpl.rdb
xrpld.rpc > xrpl.resource
xrpld.rpc > xrpl.server
xrpld.rpc > xrpl.shamap
xrpld.rpc > xrpl.tx
xrpld.shamap > xrpl.basics
xrpld.shamap > xrpld.core
xrpld.shamap > xrpl.protocol
xrpld.shamap > xrpl.shamap

View File

@@ -82,7 +82,7 @@ jobs:
- name: Create documentation artifact
if: ${{ github.event.repository.visibility == 'public' && github.event_name == 'push' }}
uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0
uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
with:
path: ${{ env.BUILD_DIR }}/docs/html

View File

@@ -153,6 +153,32 @@ jobs:
${CMAKE_ARGS} \
..
- name: Check protocol autogen files are up-to-date
working-directory: ${{ env.BUILD_DIR }}
env:
MESSAGE: |
The generated protocol wrapper classes are out of date.
This typically happens when the macro files or generator scripts
have changed but the generated files were not regenerated.
To fix this:
1. Run: cmake --build . --target setup_code_gen
2. Run: cmake --build . --target code_gen
3. Commit and push the regenerated files
run: |
set -e
cmake --build . --target setup_code_gen
cmake --build . --target code_gen
DIFF=$(git -C .. status --porcelain -- include/xrpl/protocol_autogen src/tests/libxrpl/protocol_autogen)
if [ -n "${DIFF}" ]; then
echo "::error::Generated protocol files are out of date"
git -C .. diff -- include/xrpl/protocol_autogen src/tests/libxrpl/protocol_autogen
echo "${MESSAGE}"
exit 1
fi
- name: Build the binary
working-directory: ${{ env.BUILD_DIR }}
env:
@@ -166,29 +192,6 @@ jobs:
--parallel "${BUILD_NPROC}" \
--target "${CMAKE_TARGET}"
- name: Check protocol autogen files are up-to-date
env:
MESSAGE: |
The generated protocol wrapper classes are out of date.
This typically happens when your branch is behind develop and
the macro files or generator scripts have changed.
To fix this:
1. Update your branch from develop (merge or rebase)
2. Build with code generation enabled (XRPL_NO_CODEGEN=OFF)
3. Commit and push the regenerated files
run: |
set -e
DIFF=$(git 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 diff -- include/xrpl/protocol_autogen src/tests/libxrpl/protocol_autogen
echo "${MESSAGE}"
exit 1
fi
- name: Show ccache statistics
if: ${{ inputs.ccache_enabled }}
run: |
@@ -200,7 +203,7 @@ jobs:
- name: Upload the binary (Linux)
if: ${{ github.event.repository.visibility == 'public' && runner.os == 'Linux' }}
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: xrpld-${{ inputs.config_name }}
path: ${{ env.BUILD_DIR }}/xrpld

View File

@@ -84,7 +84,7 @@ jobs:
- name: Upload clang-tidy output
if: ${{ github.event.repository.visibility == 'public' && steps.run_clang_tidy.outcome != 'success' }}
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: clang-tidy-results
path: clang-tidy-output.txt

1
.gitignore vendored
View File

@@ -13,6 +13,7 @@
Debug/
Release/
/.build/
/.venv/
/build/
/db/
/out.txt

View File

@@ -459,6 +459,21 @@ install ccache --version 4.11.3 --allow-downgrade`.
The location of `xrpld` binary in your build directory depends on your
CMake generator. Pass `--help` to see the rest of the command line options.
## Code generation
The protocol wrapper classes in `include/xrpl/protocol_autogen/` are generated
from macro definition files in `include/xrpl/protocol/detail/`. If you modify
the macro files (e.g. `transactions.macro`, `ledger_entries.macro`) or the
generation scripts/templates in `cmake/scripts/codegen/`, you need to regenerate the
files:
```
cmake --build . --target setup_code_gen # create venv and install dependencies (once)
cmake --build . --target code_gen # regenerate code
```
The regenerated files should be committed alongside your changes.
## Coverage report
The coverage report is intended for developers using compilers GCC

View File

@@ -132,6 +132,7 @@ if(coverage)
endif()
include(XrplCore)
include(XrplProtocolAutogen)
include(XrplInstall)
include(XrplValidatorKeys)

View File

@@ -108,24 +108,12 @@ target_link_libraries(
)
# Level 05
## Set up code generation for protocol_autogen module
include(XrplProtocolAutogen)
# Must call setup_protocol_autogen before add_module so that:
# 1. Stale generated files are cleared before GLOB runs
# 2. Output file list is known for custom commands
setup_protocol_autogen()
add_module(xrpl protocol_autogen)
target_link_libraries(
xrpl.libxrpl.protocol_autogen
PUBLIC xrpl.libxrpl.protocol
)
# Ensure code generation runs before compiling protocol_autogen
if(TARGET protocol_autogen_generate)
add_dependencies(xrpl.libxrpl.protocol_autogen protocol_autogen_generate)
endif()
# Level 06
add_module(xrpl core)
target_link_libraries(

View File

@@ -2,308 +2,145 @@
Protocol Autogen - Code generation for protocol wrapper classes
#]===================================================================]
# Options for code generation
option(
XRPL_NO_CODEGEN
"Disable code generation (use pre-generated files from repository)"
OFF
)
set(CODEGEN_VENV_DIR
""
"${CMAKE_CURRENT_SOURCE_DIR}/.venv"
CACHE PATH
"Path to Python virtual environment for code generation. If provided, automatic venv setup is skipped."
"Path to a Python virtual environment for code generation. A venv will be created here by setup_code_gen and used to run generation scripts."
)
# Function to set up code generation for protocol_autogen module
# This runs at configure time to generate C++ wrapper classes from macro files
function(setup_protocol_autogen)
# Directory paths
set(MACRO_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include/xrpl/protocol/detail")
set(AUTOGEN_HEADER_DIR
"${CMAKE_CURRENT_SOURCE_DIR}/include/xrpl/protocol_autogen"
)
set(AUTOGEN_TEST_DIR
"${CMAKE_CURRENT_SOURCE_DIR}/src/tests/libxrpl/protocol_autogen"
)
set(SCRIPTS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/scripts")
# Directory paths
set(MACRO_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include/xrpl/protocol/detail")
set(AUTOGEN_HEADER_DIR
"${CMAKE_CURRENT_SOURCE_DIR}/include/xrpl/protocol_autogen"
)
set(AUTOGEN_TEST_DIR
"${CMAKE_CURRENT_SOURCE_DIR}/src/tests/libxrpl/protocol_autogen"
)
set(SCRIPTS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/cmake/scripts/codegen")
# Input macro files
set(TRANSACTIONS_MACRO "${MACRO_DIR}/transactions.macro")
set(LEDGER_ENTRIES_MACRO "${MACRO_DIR}/ledger_entries.macro")
set(SFIELDS_MACRO "${MACRO_DIR}/sfields.macro")
# Input macro files
set(TRANSACTIONS_MACRO "${MACRO_DIR}/transactions.macro")
set(LEDGER_ENTRIES_MACRO "${MACRO_DIR}/ledger_entries.macro")
set(SFIELDS_MACRO "${MACRO_DIR}/sfields.macro")
# Python scripts and templates
set(GENERATE_TX_SCRIPT "${SCRIPTS_DIR}/generate_tx_classes.py")
set(GENERATE_LEDGER_SCRIPT "${SCRIPTS_DIR}/generate_ledger_classes.py")
set(REQUIREMENTS_FILE "${SCRIPTS_DIR}/requirements.txt")
set(MACRO_PARSER_COMMON "${SCRIPTS_DIR}/macro_parser_common.py")
set(TX_TEMPLATE "${SCRIPTS_DIR}/templates/Transaction.h.mako")
set(TX_TEST_TEMPLATE "${SCRIPTS_DIR}/templates/TransactionTests.cpp.mako")
set(LEDGER_TEMPLATE "${SCRIPTS_DIR}/templates/LedgerEntry.h.mako")
set(LEDGER_TEST_TEMPLATE
"${SCRIPTS_DIR}/templates/LedgerEntryTests.cpp.mako"
# Python scripts and templates
set(GENERATE_TX_SCRIPT "${SCRIPTS_DIR}/generate_tx_classes.py")
set(GENERATE_LEDGER_SCRIPT "${SCRIPTS_DIR}/generate_ledger_classes.py")
set(REQUIREMENTS_FILE "${SCRIPTS_DIR}/requirements.txt")
set(MACRO_PARSER_COMMON "${SCRIPTS_DIR}/macro_parser_common.py")
set(TX_TEMPLATE "${SCRIPTS_DIR}/templates/Transaction.h.mako")
set(TX_TEST_TEMPLATE "${SCRIPTS_DIR}/templates/TransactionTests.cpp.mako")
set(LEDGER_TEMPLATE "${SCRIPTS_DIR}/templates/LedgerEntry.h.mako")
set(LEDGER_TEST_TEMPLATE "${SCRIPTS_DIR}/templates/LedgerEntryTests.cpp.mako")
set(ALL_INPUT_FILES
"${TRANSACTIONS_MACRO}"
"${LEDGER_ENTRIES_MACRO}"
"${SFIELDS_MACRO}"
"${GENERATE_TX_SCRIPT}"
"${GENERATE_LEDGER_SCRIPT}"
"${REQUIREMENTS_FILE}"
"${MACRO_PARSER_COMMON}"
"${TX_TEMPLATE}"
"${TX_TEST_TEMPLATE}"
"${LEDGER_TEMPLATE}"
"${LEDGER_TEST_TEMPLATE}"
)
# Create output directories
file(MAKE_DIRECTORY "${AUTOGEN_HEADER_DIR}/transactions")
file(MAKE_DIRECTORY "${AUTOGEN_HEADER_DIR}/ledger_entries")
file(MAKE_DIRECTORY "${AUTOGEN_TEST_DIR}/ledger_entries")
file(MAKE_DIRECTORY "${AUTOGEN_TEST_DIR}/transactions")
# Find Python3
if(NOT Python3_EXECUTABLE)
find_package(Python3 COMPONENTS Interpreter QUIET)
endif()
if(NOT Python3_EXECUTABLE)
find_program(Python3_EXECUTABLE NAMES python3 python)
endif()
if(NOT Python3_EXECUTABLE)
message(
WARNING
"Python3 not found. The 'code_gen' and 'setup_code_gen' targets will not be available."
)
return()
endif()
# Check if code generation is disabled
if(XRPL_NO_CODEGEN)
# Warn if pip is configured with a non-default index (may need VPN).
execute_process(
COMMAND ${Python3_EXECUTABLE} -m pip config get global.index-url
OUTPUT_VARIABLE PIP_INDEX_URL
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
RESULT_VARIABLE PIP_CONFIG_RESULT
)
if(PIP_CONFIG_RESULT EQUAL 0 AND PIP_INDEX_URL)
if(
NOT PIP_INDEX_URL STREQUAL "https://pypi.org/simple"
AND NOT PIP_INDEX_URL STREQUAL "https://pypi.python.org/simple"
)
message(
WARNING
"Protocol autogen: Code generation is disabled (XRPL_NO_CODEGEN=ON). "
"Generated files may be out of date."
"Private pip index URL detected: ${PIP_INDEX_URL}\n"
"You may need to connect to VPN to access this URL."
)
return()
endif()
endif()
# Create output directories
file(MAKE_DIRECTORY "${AUTOGEN_HEADER_DIR}/transactions")
file(MAKE_DIRECTORY "${AUTOGEN_HEADER_DIR}/ledger_entries")
file(MAKE_DIRECTORY "${AUTOGEN_TEST_DIR}/ledger_entries")
file(MAKE_DIRECTORY "${AUTOGEN_TEST_DIR}/transactions")
# Find Python3 - check if already found by Conan or find it ourselves
if(NOT Python3_EXECUTABLE)
find_package(Python3 COMPONENTS Interpreter QUIET)
endif()
if(NOT Python3_EXECUTABLE)
# Try finding python3 executable directly
find_program(Python3_EXECUTABLE NAMES python3 python)
endif()
if(NOT Python3_EXECUTABLE)
message(
FATAL_ERROR
"Python3 not found. Code generation cannot proceed.\n"
"Please install Python 3, or set -DXRPL_NO_CODEGEN=ON to use existing generated files."
)
return()
endif()
message(STATUS "Using Python3 for code generation: ${Python3_EXECUTABLE}")
# Set up Python virtual environment for code generation
if(CODEGEN_VENV_DIR)
# User-provided venv - skip automatic setup
set(VENV_DIR "${CODEGEN_VENV_DIR}")
message(STATUS "Using user-provided Python venv: ${VENV_DIR}")
else()
# Use default venv in build directory
set(VENV_DIR "${CMAKE_CURRENT_BINARY_DIR}/codegen_venv")
endif()
# Determine the Python executable path in the venv
# Determine which Python interpreter to use for code generation.
if(CODEGEN_VENV_DIR)
if(WIN32)
set(VENV_PYTHON "${VENV_DIR}/Scripts/python.exe")
set(VENV_PIP "${VENV_DIR}/Scripts/pip.exe")
set(CODEGEN_PYTHON "${CODEGEN_VENV_DIR}/Scripts/python.exe")
else()
set(VENV_PYTHON "${VENV_DIR}/bin/python")
set(VENV_PIP "${VENV_DIR}/bin/pip")
set(CODEGEN_PYTHON "${CODEGEN_VENV_DIR}/bin/python")
endif()
# Only auto-setup venv if not user-provided
if(NOT CODEGEN_VENV_DIR)
# Check if venv needs to be created or updated
set(VENV_NEEDS_UPDATE FALSE)
if(NOT EXISTS "${VENV_PYTHON}")
set(VENV_NEEDS_UPDATE TRUE)
message(
STATUS
"Creating Python virtual environment for code generation..."
)
elseif(
"${REQUIREMENTS_FILE}"
IS_NEWER_THAN
"${VENV_DIR}/.requirements_installed"
)
set(VENV_NEEDS_UPDATE TRUE)
message(
STATUS
"Updating Python virtual environment (requirements changed)..."
)
endif()
# Create/update virtual environment if needed
if(VENV_NEEDS_UPDATE)
message(
STATUS
"Setting up Python virtual environment at ${VENV_DIR}"
)
execute_process(
COMMAND ${Python3_EXECUTABLE} -m venv "${VENV_DIR}"
RESULT_VARIABLE VENV_RESULT
ERROR_VARIABLE VENV_ERROR
)
if(NOT VENV_RESULT EQUAL 0)
message(
FATAL_ERROR
"Failed to create virtual environment: ${VENV_ERROR}"
)
endif()
# Check pip index URL configuration
execute_process(
COMMAND ${VENV_PIP} config get global.index-url
OUTPUT_VARIABLE PIP_INDEX_URL
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
# Default PyPI URL
set(DEFAULT_PIP_INDEX "https://pypi.org/simple")
# Show warning if using non-default index
if(PIP_INDEX_URL AND NOT PIP_INDEX_URL STREQUAL "")
if(NOT PIP_INDEX_URL STREQUAL DEFAULT_PIP_INDEX)
message(
WARNING
"Private pip index URL detected: ${PIP_INDEX_URL}\n"
"You may need to connect to VPN to access this URL."
)
endif()
endif()
message(STATUS "Installing Python dependencies...")
execute_process(
COMMAND ${VENV_PIP} install --upgrade pip
RESULT_VARIABLE PIP_UPGRADE_RESULT
OUTPUT_QUIET
ERROR_VARIABLE PIP_UPGRADE_ERROR
)
if(NOT PIP_UPGRADE_RESULT EQUAL 0)
message(WARNING "Failed to upgrade pip: ${PIP_UPGRADE_ERROR}")
endif()
execute_process(
COMMAND ${VENV_PIP} install -r "${REQUIREMENTS_FILE}"
RESULT_VARIABLE PIP_INSTALL_RESULT
ERROR_VARIABLE PIP_INSTALL_ERROR
)
if(NOT PIP_INSTALL_RESULT EQUAL 0)
message(
FATAL_ERROR
"Failed to install Python dependencies: ${PIP_INSTALL_ERROR}"
)
endif()
# Mark requirements as installed
file(TOUCH "${VENV_DIR}/.requirements_installed")
message(STATUS "Python virtual environment ready")
endif()
endif()
# At configure time - get list of output files for transactions
execute_process(
COMMAND
${VENV_PYTHON} "${GENERATE_TX_SCRIPT}" "${TRANSACTIONS_MACRO}"
--header-dir "${AUTOGEN_HEADER_DIR}/transactions" --test-dir
"${AUTOGEN_TEST_DIR}/transactions" --list-outputs
OUTPUT_VARIABLE TX_OUTPUT_FILES
OUTPUT_STRIP_TRAILING_WHITESPACE
RESULT_VARIABLE TX_LIST_RESULT
ERROR_VARIABLE TX_LIST_ERROR
else()
set(CODEGEN_PYTHON "${Python3_EXECUTABLE}")
message(
WARNING
"CODEGEN_VENV_DIR is not set. Dependencies will be installed globally.\n"
"If this is not intended, reconfigure with:\n"
" cmake . -UCODEGEN_VENV_DIR"
)
if(NOT TX_LIST_RESULT EQUAL 0)
message(
FATAL_ERROR
"Failed to list transaction output files:\n${TX_LIST_ERROR}"
)
endif()
# Convert newline-separated list to CMake list
string(REPLACE "\\" "/" TX_OUTPUT_FILES "${TX_OUTPUT_FILES}")
string(REPLACE "\n" ";" TX_OUTPUT_FILES "${TX_OUTPUT_FILES}")
endif()
# At configure time - get list of output files for ledger entries
execute_process(
COMMAND
${VENV_PYTHON} "${GENERATE_LEDGER_SCRIPT}" "${LEDGER_ENTRIES_MACRO}"
--header-dir "${AUTOGEN_HEADER_DIR}/ledger_entries" --test-dir
"${AUTOGEN_TEST_DIR}/ledger_entries" --list-outputs
OUTPUT_VARIABLE LEDGER_OUTPUT_FILES
OUTPUT_STRIP_TRAILING_WHITESPACE
RESULT_VARIABLE LEDGER_LIST_RESULT
ERROR_VARIABLE LEDGER_LIST_ERROR
)
if(NOT LEDGER_LIST_RESULT EQUAL 0)
message(
FATAL_ERROR
"Failed to list ledger entry output files:\n${LEDGER_LIST_ERROR}"
)
endif()
# Convert newline-separated list to CMake list
string(REPLACE "\\" "/" LEDGER_OUTPUT_FILES "${LEDGER_OUTPUT_FILES}")
string(REPLACE "\n" ";" LEDGER_OUTPUT_FILES "${LEDGER_OUTPUT_FILES}")
# Custom command to generate transaction classes at build time
add_custom_command(
OUTPUT ${TX_OUTPUT_FILES}
COMMAND
${VENV_PYTHON} "${GENERATE_TX_SCRIPT}" "${TRANSACTIONS_MACRO}"
--header-dir "${AUTOGEN_HEADER_DIR}/transactions" --test-dir
"${AUTOGEN_TEST_DIR}/transactions" --sfields-macro
"${SFIELDS_MACRO}"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
DEPENDS
"${TRANSACTIONS_MACRO}"
"${SFIELDS_MACRO}"
"${GENERATE_TX_SCRIPT}"
"${MACRO_PARSER_COMMON}"
"${TX_TEMPLATE}"
"${TX_TEST_TEMPLATE}"
"${REQUIREMENTS_FILE}"
COMMENT "Generating transaction classes from transactions.macro..."
VERBATIM
)
# Custom command to generate ledger entry classes at build time
add_custom_command(
OUTPUT ${LEDGER_OUTPUT_FILES}
COMMAND
${VENV_PYTHON} "${GENERATE_LEDGER_SCRIPT}" "${LEDGER_ENTRIES_MACRO}"
--header-dir "${AUTOGEN_HEADER_DIR}/ledger_entries" --test-dir
"${AUTOGEN_TEST_DIR}/ledger_entries" --sfields-macro
"${SFIELDS_MACRO}"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
DEPENDS
"${LEDGER_ENTRIES_MACRO}"
"${SFIELDS_MACRO}"
"${GENERATE_LEDGER_SCRIPT}"
"${MACRO_PARSER_COMMON}"
"${LEDGER_TEMPLATE}"
"${LEDGER_TEST_TEMPLATE}"
"${REQUIREMENTS_FILE}"
COMMENT "Generating ledger entry classes from ledger_entries.macro..."
VERBATIM
)
# Create a custom target that depends on all generated files
# Custom target to create a venv and install Python dependencies.
# Run manually with: cmake --build . --target setup_code_gen
if(CODEGEN_VENV_DIR)
add_custom_target(
protocol_autogen_generate
DEPENDS ${TX_OUTPUT_FILES} ${LEDGER_OUTPUT_FILES}
COMMENT "Protocol autogen code generation"
setup_code_gen
COMMAND ${Python3_EXECUTABLE} -m venv "${CODEGEN_VENV_DIR}"
COMMAND ${CODEGEN_PYTHON} -m pip install -r "${REQUIREMENTS_FILE}"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT "Creating venv and installing code generation dependencies..."
)
else()
add_custom_target(
setup_code_gen
COMMAND ${Python3_EXECUTABLE} -m pip install -r "${REQUIREMENTS_FILE}"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT "Installing code generation dependencies..."
)
endif()
# Extract test files from output lists (files ending in Tests.cpp)
set(PROTOCOL_AUTOGEN_TEST_SOURCES "")
foreach(FILE ${TX_OUTPUT_FILES} ${LEDGER_OUTPUT_FILES})
if(FILE MATCHES "Tests\\.cpp$")
list(APPEND PROTOCOL_AUTOGEN_TEST_SOURCES "${FILE}")
endif()
endforeach()
# Export test sources to parent scope for use in test CMakeLists.txt
set(PROTOCOL_AUTOGEN_TEST_SOURCES
"${PROTOCOL_AUTOGEN_TEST_SOURCES}"
CACHE INTERNAL
"Generated protocol_autogen test sources"
)
# Register dependencies so CMake reconfigures when macro files change
# (to update the list of output files)
set_property(
DIRECTORY
APPEND
PROPERTY
CMAKE_CONFIGURE_DEPENDS
"${TRANSACTIONS_MACRO}"
"${LEDGER_ENTRIES_MACRO}"
)
endfunction()
# Custom target for code generation, excluded from ALL.
# Run manually with: cmake --build . --target code_gen
add_custom_target(
code_gen
COMMAND
${CMAKE_COMMAND} -DCODEGEN_PYTHON=${CODEGEN_PYTHON}
-DGENERATE_TX_SCRIPT=${GENERATE_TX_SCRIPT}
-DGENERATE_LEDGER_SCRIPT=${GENERATE_LEDGER_SCRIPT}
-DTRANSACTIONS_MACRO=${TRANSACTIONS_MACRO}
-DLEDGER_ENTRIES_MACRO=${LEDGER_ENTRIES_MACRO}
-DSFIELDS_MACRO=${SFIELDS_MACRO}
-DAUTOGEN_HEADER_DIR=${AUTOGEN_HEADER_DIR}
-DAUTOGEN_TEST_DIR=${AUTOGEN_TEST_DIR} -P
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/XrplProtocolAutogenRun.cmake"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT "Running protocol code generation..."
SOURCES ${ALL_INPUT_FILES}
)

View File

@@ -0,0 +1,39 @@
#[===================================================================[
Protocol Autogen - Run script invoked by the 'code_gen' target
#]===================================================================]
# Generate transaction classes.
execute_process(
COMMAND
${CODEGEN_PYTHON} "${GENERATE_TX_SCRIPT}" "${TRANSACTIONS_MACRO}"
--header-dir "${AUTOGEN_HEADER_DIR}/transactions" --test-dir
"${AUTOGEN_TEST_DIR}/transactions" --sfields-macro "${SFIELDS_MACRO}"
RESULT_VARIABLE TX_RESULT
OUTPUT_VARIABLE TX_OUTPUT
ERROR_VARIABLE TX_ERROR
)
if(NOT TX_RESULT EQUAL 0)
message(
FATAL_ERROR
"Transaction code generation failed:\n${TX_OUTPUT}\n${TX_ERROR}\n${TX_RESULT}"
)
endif()
# Generate ledger entry classes.
execute_process(
COMMAND
${CODEGEN_PYTHON} "${GENERATE_LEDGER_SCRIPT}" "${LEDGER_ENTRIES_MACRO}"
--header-dir "${AUTOGEN_HEADER_DIR}/ledger_entries" --test-dir
"${AUTOGEN_TEST_DIR}/ledger_entries" --sfields-macro "${SFIELDS_MACRO}"
RESULT_VARIABLE LEDGER_RESULT
OUTPUT_VARIABLE LEDGER_OUTPUT
ERROR_VARIABLE LEDGER_ERROR
)
if(NOT LEDGER_RESULT EQUAL 0)
message(
FATAL_ERROR
"Ledger entry code generation failed:\n${LEDGER_OUTPUT}\n${LEDGER_ERROR}\n${TX_RESULT}"
)
endif()
message(STATUS "Protocol autogen: code generation complete")

View File

@@ -138,28 +138,12 @@ def main():
"--sfields-macro",
help="Path to sfields.macro (default: auto-detect from macro_path)",
)
parser.add_argument(
"--list-outputs",
action="store_true",
help="List output files without generating (one per line)",
)
parser.add_argument("--venv-dir", help=argparse.SUPPRESS)
args = parser.parse_args()
# Parse the macro file to get ledger entry names
entries = parse_macro_file(args.macro_path)
# If --list-outputs, just print the output file paths and exit
if args.list_outputs:
header_dir = Path(args.header_dir)
for entry in entries:
print(header_dir / f"{entry['name']}.h")
if args.test_dir:
test_dir = Path(args.test_dir)
for entry in entries:
print(test_dir / f"{entry['name']}Tests.cpp")
return
# Auto-detect sfields.macro path if not provided
if args.sfields_macro:
sfields_path = Path(args.sfields_macro)

View File

@@ -147,28 +147,12 @@ def main():
"--sfields-macro",
help="Path to sfields.macro (default: auto-detect from macro_path)",
)
parser.add_argument(
"--list-outputs",
action="store_true",
help="List output files without generating (one per line)",
)
parser.add_argument("--venv-dir", help=argparse.SUPPRESS)
args = parser.parse_args()
# Parse the macro file to get transaction names
transactions = parse_macro_file(args.macro_path)
# If --list-outputs, just print the output file paths and exit
if args.list_outputs:
header_dir = Path(args.header_dir)
for tx in transactions:
print(header_dir / f"{tx['name']}.h")
if args.test_dir:
test_dir = Path(args.test_dir)
for tx in transactions:
print(test_dir / f"{tx['name']}Tests.cpp")
return
# Auto-detect sfields.macro path if not provided
if args.sfields_macro:
sfields_path = Path(args.sfields_macro)

View File

@@ -67,9 +67,13 @@ public:
legacy(std::string value)
{
if (lines_.empty())
{
lines_.emplace_back(std::move(value));
}
else
{
lines_[0] = std::move(value);
}
}
/**
@@ -84,8 +88,10 @@ public:
if (lines_.empty())
return "";
if (lines_.size() > 1)
{
Throw<std::runtime_error>(
"A legacy value must have exactly one line. Section: " + name_);
}
return lines_[0];
}

View File

@@ -24,7 +24,8 @@ public:
Buffer() = default;
/** Create an uninitialized buffer with the given size. */
explicit Buffer(std::size_t size) : p_(size ? new std::uint8_t[size] : nullptr), size_(size)
explicit Buffer(std::size_t size)
: p_((size != 0u) ? new std::uint8_t[size] : nullptr), size_(size)
{
}
@@ -36,7 +37,7 @@ public:
*/
Buffer(void const* data, std::size_t size) : Buffer(size)
{
if (size)
if (size != 0u)
std::memcpy(p_.get(), data, size);
}
@@ -114,7 +115,7 @@ public:
operator Slice() const noexcept
{
if (!size_)
if (size_ == 0u)
return Slice{};
return Slice{p_.get(), size_};
}
@@ -155,7 +156,7 @@ public:
{
if (n != size_)
{
p_.reset(n ? new std::uint8_t[n] : nullptr);
p_.reset((n != 0u) ? new std::uint8_t[n] : nullptr);
size_ = n;
}
return p_.get();
@@ -199,7 +200,7 @@ operator==(Buffer const& lhs, Buffer const& rhs) noexcept
if (lhs.size() != rhs.size())
return false;
if (lhs.size() == 0)
if (lhs.empty())
return true;
return std::memcmp(lhs.data(), rhs.data(), lhs.size()) == 0;

View File

@@ -68,12 +68,15 @@ lz4Decompress(
if (decompressedSize <= 0)
Throw<std::runtime_error>("lz4Decompress: integer overflow (output)");
// NOLINTNEXTLINE(readability-suspicious-call-argument)
if (LZ4_decompress_safe(
reinterpret_cast<char const*>(in),
reinterpret_cast<char*>(decompressed),
inSize,
decompressedSize) != decompressedSize)
{
Throw<std::runtime_error>("lz4Decompress: failed");
}
return decompressedSize;
}

View File

@@ -67,7 +67,7 @@ private:
}
else
{
while (elapsed--)
while ((elapsed--) != 0u)
m_value -= (m_value + Window - 1) / Window;
}
}

View File

@@ -247,7 +247,7 @@ IntrusiveRefCounts::releaseStrongRef() const
using enum ReleaseStrongRefAction;
auto prevIntVal = refCounts.load(std::memory_order_acquire);
while (1)
while (true)
{
RefCountPair const prevVal{prevIntVal};
XRPL_ASSERT(
@@ -298,7 +298,7 @@ IntrusiveRefCounts::addWeakReleaseStrongRef() const
// Note: If this becomes a perf bottleneck, the `partialDestroyStartedMask`
// may be able to be set non-atomically. But it is easier to reason about
// the code if the flag is set atomically.
while (1)
while (true)
{
RefCountPair const prevVal{prevIntVal};
// Converted the last strong pointer to a weak pointer.
@@ -343,7 +343,7 @@ IntrusiveRefCounts::releaseWeakRef() const
RefCountPair prev = prevIntVal;
if (prev.weak == 1 && prev.strong == 0)
{
if (!prev.partialDestroyStartedBit)
if (prev.partialDestroyStartedBit == 0u)
{
// This case should only be hit if the partialDestroyStartedBit is
// set non-atomically (and even then very rarely). The code is kept
@@ -352,7 +352,7 @@ IntrusiveRefCounts::releaseWeakRef() const
prevIntVal = refCounts.load(std::memory_order_acquire);
prev = RefCountPair{prevIntVal};
}
if (!prev.partialDestroyFinishedBit)
if (prev.partialDestroyFinishedBit == 0u)
{
// partial destroy MUST finish before running a full destroy (when
// using weak pointers)
@@ -372,7 +372,7 @@ IntrusiveRefCounts::checkoutStrongRefFromWeak() const noexcept
while (!refCounts.compare_exchange_weak(curValue, desiredValue, std::memory_order_acq_rel))
{
RefCountPair const prev{curValue};
if (!prev.strong)
if (prev.strong == 0u)
return false;
desiredValue = curValue + strongDelta;

View File

@@ -42,10 +42,10 @@ struct LocalValues
// Keys are the address of a LocalValue.
std::unordered_map<void const*, std::unique_ptr<BasicValue>> values;
static inline void
static void
cleanup(LocalValues* lvs)
{
if (lvs && !lvs->onCoro)
if ((lvs != nullptr) && !lvs->onCoro)
delete lvs;
}
};
@@ -89,7 +89,7 @@ T&
LocalValue<T>::operator*()
{
auto lvs = detail::getLocalValues().get();
if (!lvs)
if (lvs == nullptr)
{
lvs = new detail::LocalValues();
lvs->onCoro = false;

View File

@@ -78,7 +78,7 @@ struct MantissaRange
}
rep min;
rep max{min * 10 - 1};
rep max{(min * 10) - 1};
int log;
mantissa_scale scale;
@@ -342,7 +342,9 @@ public:
constexpr int
signum() const noexcept
{
return negative_ ? -1 : (mantissa_ ? 1 : 0);
if (negative_)
return -1;
return (mantissa_ != 0u) ? 1 : 0;
}
Number
@@ -402,19 +404,19 @@ public:
static void
setMantissaScale(MantissaRange::mantissa_scale scale);
inline static internalrep
static internalrep
minMantissa()
{
return range_.get().min;
}
inline static internalrep
static internalrep
maxMantissa()
{
return range_.get().max;
}
inline static int
static int
mantissaLog()
{
return range_.get().log;
@@ -507,16 +509,12 @@ private:
class Guard;
};
inline constexpr Number::Number(
bool negative,
internalrep mantissa,
int exponent,
unchecked) noexcept
constexpr Number::Number(bool negative, internalrep mantissa, int exponent, unchecked) noexcept
: negative_(negative), mantissa_{mantissa}, exponent_{exponent}
{
}
inline constexpr Number::Number(internalrep mantissa, int exponent, unchecked) noexcept
constexpr Number::Number(internalrep mantissa, int exponent, unchecked) noexcept
: Number(false, mantissa, exponent, unchecked{})
{
}
@@ -548,7 +546,7 @@ inline Number::Number(rep mantissa) : Number{mantissa, 0}
* Please see the "---- External Interface ----" section of the class
* documentation for an explanation of why the internal value may be modified.
*/
inline constexpr Number::rep
constexpr Number::rep
Number::mantissa() const noexcept
{
auto m = mantissa_;
@@ -569,7 +567,7 @@ Number::mantissa() const noexcept
* Please see the "---- External Interface ----" section of the class
* documentation for an explanation of why the internal value may be modified.
*/
inline constexpr int
constexpr int
Number::exponent() const noexcept
{
auto e = exponent_;
@@ -584,13 +582,13 @@ Number::exponent() const noexcept
return e;
}
inline constexpr Number
constexpr Number
Number::operator+() const noexcept
{
return *this;
}
inline constexpr Number
constexpr Number
Number::operator-() const noexcept
{
if (mantissa_ == 0)
@@ -705,17 +703,19 @@ Number::normalizeToRange(T minMantissa, T maxMantissa) const
int exponent = exponent_;
if constexpr (std::is_unsigned_v<T>)
{
XRPL_ASSERT_PARTS(
!negative,
"xrpl::Number::normalizeToRange",
"Number is non-negative for unsigned range.");
}
Number::normalize(negative, mantissa, exponent, minMantissa, maxMantissa);
auto const sign = negative ? -1 : 1;
return std::make_pair(static_cast<T>(sign * mantissa), exponent);
}
inline constexpr Number
constexpr Number
abs(Number x) noexcept
{
if (x < Number{})
@@ -746,7 +746,7 @@ power(Number const& f, unsigned n, unsigned d);
// Return 0 if abs(x) < limit, else returns x
inline constexpr Number
constexpr Number
squelch(Number const& x, Number const& limit) noexcept
{
if (abs(x) < limit)

View File

@@ -117,22 +117,32 @@ from_string(RangeSet<T>& rs, std::string const& s)
case 1: {
T front;
if (!beast::lexicalCastChecked(front, intervals.front()))
{
result = false;
}
else
{
rs.insert(front);
}
break;
}
case 2: {
T front;
if (!beast::lexicalCastChecked(front, intervals.front()))
{
result = false;
}
else
{
T back;
if (!beast::lexicalCastChecked(back, intervals.back()))
{
result = false;
}
else
{
rs.insert(range(front, back));
}
}
break;
}

View File

@@ -98,7 +98,7 @@ class SlabAllocator
ret = l_;
if (ret)
if (ret != nullptr)
{
// Use memcpy to avoid unaligned UB
// (will optimize to equivalent code)
@@ -159,7 +159,7 @@ public:
std::size_t extra,
std::size_t alloc = 0,
std::size_t align = 0)
: itemAlignment_(align ? align : alignof(Type))
: itemAlignment_((align != 0u) ? align : alignof(Type))
, itemSize_(boost::alignment::align_up(sizeof(Type) + extra, itemAlignment_))
, slabSize_(alloc)
{
@@ -215,7 +215,7 @@ public:
// We want to allocate the memory at a 2 MiB boundary, to make it
// possible to use hugepage mappings on Linux:
auto buf = boost::alignment::aligned_alloc(megabytes(std::size_t(2)), size);
if (!buf) [[unlikely]]
if (buf == nullptr) [[unlikely]]
return nullptr;
#if BOOST_OS_LINUX
@@ -235,7 +235,7 @@ public:
// This operation is essentially guaranteed not to fail but
// let's be careful anyways.
if (!boost::alignment::align(itemAlignment_, itemSize_, slabData, slabSize))
if (boost::alignment::align(itemAlignment_, itemSize_, slabData, slabSize) == nullptr)
{
boost::alignment::aligned_free(buf);
return nullptr;

View File

@@ -183,7 +183,7 @@ operator==(Slice const& lhs, Slice const& rhs) noexcept
if (lhs.size() != rhs.size())
return false;
if (lhs.size() == 0)
if (lhs.empty())
return true;
return std::memcmp(lhs.data(), rhs.data(), lhs.size()) == 0;

View File

@@ -23,8 +23,10 @@ generalized_set_intersection(
{
while (first1 != last1 && first2 != last2)
{
if (comp(*first1, *first2)) // if *first1 < *first2
++first1; // then reduce first range
if (comp(*first1, *first2))
{ // if *first1 < *first2
++first1; // then reduce first range
}
else
{
if (!comp(*first2, *first1)) // if *first1 == *first2

View File

@@ -183,11 +183,17 @@ private:
return ParseResult::badChar;
if (c >= 'a')
{
nibble = static_cast<std::uint32_t>(c - 'a' + 0xA);
}
else if (c >= 'A')
{
nibble = static_cast<std::uint32_t>(c - 'A' + 0xA);
}
else if (c <= '9')
{
nibble = static_cast<std::uint32_t>(c - '0');
}
if (nibble > 0xFu)
return ParseResult::badChar;
@@ -308,8 +314,10 @@ public:
signum() const
{
for (int i = 0; i < WIDTH; i++)
{
if (data_[i] != 0)
return 1;
}
return 0;
}
@@ -390,7 +398,7 @@ public:
return *this;
}
base_uint const
base_uint
operator++(int)
{
// postfix operator
@@ -415,7 +423,7 @@ public:
return *this;
}
base_uint const
base_uint
operator--(int)
{
// postfix operator
@@ -444,7 +452,7 @@ public:
{
std::uint64_t carry = 0;
for (int i = WIDTH; i--;)
for (int i = WIDTH - 1; i >= 0; i--)
{
std::uint64_t const n = carry + boost::endian::big_to_native(data_[i]) +
boost::endian::big_to_native(b.data_[i]);
@@ -532,7 +540,7 @@ using uint256 = base_uint<256>;
using uint192 = base_uint<192>;
template <std::size_t Bits, class Tag>
[[nodiscard]] inline constexpr std::strong_ordering
[[nodiscard]] constexpr std::strong_ordering
operator<=>(base_uint<Bits, Tag> const& lhs, base_uint<Bits, Tag> const& rhs)
{
// This comparison might seem wrong on a casual inspection because it
@@ -553,7 +561,7 @@ operator<=>(base_uint<Bits, Tag> const& lhs, base_uint<Bits, Tag> const& rhs)
}
template <std::size_t Bits, typename Tag>
[[nodiscard]] inline constexpr bool
[[nodiscard]] constexpr bool
operator==(base_uint<Bits, Tag> const& lhs, base_uint<Bits, Tag> const& rhs)
{
return (lhs <=> rhs) == 0;
@@ -561,7 +569,7 @@ operator==(base_uint<Bits, Tag> const& lhs, base_uint<Bits, Tag> const& rhs)
//------------------------------------------------------------------------------
template <std::size_t Bits, class Tag>
inline constexpr bool
constexpr bool
operator==(base_uint<Bits, Tag> const& a, std::uint64_t b)
{
return a == base_uint<Bits, Tag>(b);
@@ -569,28 +577,28 @@ operator==(base_uint<Bits, Tag> const& a, std::uint64_t b)
//------------------------------------------------------------------------------
template <std::size_t Bits, class Tag>
inline constexpr base_uint<Bits, Tag>
constexpr base_uint<Bits, Tag>
operator^(base_uint<Bits, Tag> const& a, base_uint<Bits, Tag> const& b)
{
return base_uint<Bits, Tag>(a) ^= b;
}
template <std::size_t Bits, class Tag>
inline constexpr base_uint<Bits, Tag>
constexpr base_uint<Bits, Tag>
operator&(base_uint<Bits, Tag> const& a, base_uint<Bits, Tag> const& b)
{
return base_uint<Bits, Tag>(a) &= b;
}
template <std::size_t Bits, class Tag>
inline constexpr base_uint<Bits, Tag>
constexpr base_uint<Bits, Tag>
operator|(base_uint<Bits, Tag> const& a, base_uint<Bits, Tag> const& b)
{
return base_uint<Bits, Tag>(a) |= b;
}
template <std::size_t Bits, class Tag>
inline constexpr base_uint<Bits, Tag>
constexpr base_uint<Bits, Tag>
operator+(base_uint<Bits, Tag> const& a, base_uint<Bits, Tag> const& b)
{
return base_uint<Bits, Tag>(a) += b;

View File

@@ -231,7 +231,8 @@ public:
{
// Set partitions to the number of hardware threads if the parameter
// is either empty or set to 0.
partitions_ = partitions && *partitions ? *partitions : std::thread::hardware_concurrency();
partitions_ =
partitions && (*partitions != 0u) ? *partitions : std::thread::hardware_concurrency();
map_.resize(partitions_);
XRPL_ASSERT(
partitions_,

View File

@@ -17,7 +17,7 @@ concept SafeToCast = (std::is_integral_v<Src> && std::is_integral_v<Dest>) &&
: sizeof(Dest) >= sizeof(Src));
template <class Dest, class Src>
inline constexpr std::enable_if_t<std::is_integral_v<Dest> && std::is_integral_v<Src>, Dest>
constexpr std::enable_if_t<std::is_integral_v<Dest> && std::is_integral_v<Src>, Dest>
safe_cast(Src s) noexcept
{
static_assert(
@@ -30,14 +30,14 @@ safe_cast(Src s) noexcept
}
template <class Dest, class Src>
inline constexpr std::enable_if_t<std::is_enum_v<Dest> && std::is_integral_v<Src>, Dest>
constexpr std::enable_if_t<std::is_enum_v<Dest> && std::is_integral_v<Src>, Dest>
safe_cast(Src s) noexcept
{
return static_cast<Dest>(safe_cast<std::underlying_type_t<Dest>>(s));
}
template <class Dest, class Src>
inline constexpr std::enable_if_t<std::is_integral_v<Dest> && std::is_enum_v<Src>, Dest>
constexpr std::enable_if_t<std::is_integral_v<Dest> && std::is_enum_v<Src>, Dest>
safe_cast(Src s) noexcept
{
return safe_cast<Dest>(static_cast<std::underlying_type_t<Src>>(s));
@@ -48,7 +48,7 @@ safe_cast(Src s) noexcept
// underlying types become safe, it can be converted to a safe_cast.
template <class Dest, class Src>
inline constexpr std::enable_if_t<std::is_integral_v<Dest> && std::is_integral_v<Src>, Dest>
constexpr std::enable_if_t<std::is_integral_v<Dest> && std::is_integral_v<Src>, Dest>
unsafe_cast(Src s) noexcept
{
static_assert(
@@ -59,14 +59,14 @@ unsafe_cast(Src s) noexcept
}
template <class Dest, class Src>
inline constexpr std::enable_if_t<std::is_enum_v<Dest> && std::is_integral_v<Src>, Dest>
constexpr std::enable_if_t<std::is_enum_v<Dest> && std::is_integral_v<Src>, Dest>
unsafe_cast(Src s) noexcept
{
return static_cast<Dest>(unsafe_cast<std::underlying_type_t<Dest>>(s));
}
template <class Dest, class Src>
inline constexpr std::enable_if_t<std::is_integral_v<Dest> && std::is_enum_v<Src>, Dest>
constexpr std::enable_if_t<std::is_integral_v<Dest> && std::is_enum_v<Src>, Dest>
unsafe_cast(Src s) noexcept
{
return unsafe_cast<Dest>(static_cast<std::underlying_type_t<Src>>(s));

View File

@@ -184,7 +184,7 @@ private:
void
operator()() const
{
if (!m_probe)
if (m_probe == nullptr)
return;
typename Clock::time_point const now(Clock::now());
typename Clock::duration const elapsed(now - m_start);
@@ -202,7 +202,7 @@ private:
// Calculate when we want to sample again, and
// adjust for the expected latency.
//
typename Clock::time_point const when(now + m_probe->m_period - 2 * elapsed);
typename Clock::time_point const when(now + m_probe->m_period - (2 * elapsed));
if (when <= now)
{
@@ -224,7 +224,7 @@ private:
void
operator()(boost::system::error_code const& ec)
{
if (!m_probe)
if (m_probe == nullptr)
return;
typename Clock::time_point const now(Clock::now());
boost::asio::post(

View File

@@ -16,10 +16,10 @@ class aged_container_iterator
{
public:
using iterator_category = typename std::iterator_traits<Iterator>::iterator_category;
using value_type = typename std::conditional<
using value_type = std::conditional_t<
is_const,
typename Iterator::value_type::stashed::value_type const,
typename Iterator::value_type::stashed::value_type>::type;
typename Iterator::value_type::stashed::value_type>;
using difference_type = typename std::iterator_traits<Iterator>::difference_type;
using pointer = value_type*;
using reference = value_type&;
@@ -32,9 +32,9 @@ public:
template <
bool other_is_const,
class OtherIterator,
class = typename std::enable_if<
(other_is_const == false || is_const == true) &&
std::is_same<Iterator, OtherIterator>::value == false>::type>
class = std::enable_if_t<
(!other_is_const || is_const) &&
!static_cast<bool>(std::is_same_v<Iterator, OtherIterator>)>>
explicit aged_container_iterator(
aged_container_iterator<other_is_const, OtherIterator> const& other)
: m_iter(other.m_iter)
@@ -42,9 +42,7 @@ public:
}
// Disable constructing a const_iterator from a non-const_iterator.
template <
bool other_is_const,
class = typename std::enable_if<other_is_const == false || is_const == true>::type>
template <bool other_is_const, class = std::enable_if_t<!other_is_const || is_const>>
aged_container_iterator(aged_container_iterator<other_is_const, Iterator> const& other)
: m_iter(other.m_iter)
{
@@ -53,8 +51,8 @@ public:
// Disable assigning a const_iterator to a non-const iterator
template <bool other_is_const, class OtherIterator>
auto
operator=(aged_container_iterator<other_is_const, OtherIterator> const& other) -> typename std::
enable_if<other_is_const == false || is_const == true, aged_container_iterator&>::type
operator=(aged_container_iterator<other_is_const, OtherIterator> const& other)
-> std::enable_if_t<!other_is_const || is_const, aged_container_iterator&>
{
m_iter = other.m_iter;
return *this;

View File

@@ -40,12 +40,12 @@ public:
std::string
print() const;
inline bool
bool
isRelease() const noexcept
{
return preReleaseIdentifiers.empty();
}
inline bool
bool
isPreRelease() const noexcept
{
return !isRelease();

View File

@@ -64,7 +64,7 @@ private:
void
flushToState(void const* data, std::size_t len)
{
if (!state_)
if (state_ == nullptr)
{
state_ = allocState();
if (seed_.has_value())
@@ -78,7 +78,7 @@ private:
}
XXH3_64bits_update(state_, readBuffer_.data(), readBuffer_.size());
resetBuffers();
if (data && len)
if ((data != nullptr) && (len != 0u))
{
XXH3_64bits_update(state_, data, len);
}
@@ -87,22 +87,18 @@ private:
result_type
retrieveHash()
{
if (state_)
if (state_ != nullptr)
{
flushToState(nullptr, 0);
return XXH3_64bits_digest(state_);
}
else
if (seed_.has_value())
{
if (seed_.has_value())
{
return XXH3_64bits_withSeed(readBuffer_.data(), readBuffer_.size(), *seed_);
}
else
{
return XXH3_64bits(readBuffer_.data(), readBuffer_.size());
}
return XXH3_64bits_withSeed(readBuffer_.data(), readBuffer_.size(), *seed_);
}
return XXH3_64bits(readBuffer_.data(), readBuffer_.size());
}
public:
@@ -119,7 +115,7 @@ public:
~xxhasher() noexcept
{
if (state_)
if (state_ != nullptr)
{
XXH3_freeState(state_);
}

View File

@@ -70,9 +70,13 @@ hash_append(Hasher& h, beast::IP::Address const& addr) noexcept
{
using beast::hash_append;
if (addr.is_v4())
{
hash_append(h, addr.to_v4().to_bytes());
}
else if (addr.is_v6())
{
hash_append(h, addr.to_v6().to_bytes());
}
else
{
// LCOV_EXCL_START

View File

@@ -69,12 +69,12 @@ public:
{
return m_addr.is_v6();
}
AddressV4 const
AddressV4
to_v4() const
{
return m_addr.to_v4();
}
AddressV6 const
AddressV6
to_v6() const
{
return m_addr.to_v6();

View File

@@ -350,8 +350,10 @@ bool
token_in_list(boost::string_ref const& value, boost::string_ref const& token)
{
for (auto const& item : make_list(value))
{
if (ci_equal(item, token))
return true;
}
return false;
}
@@ -360,8 +362,10 @@ bool
is_keep_alive(boost::beast::http::message<isRequest, Body, Fields> const& m)
{
if (m.version() <= 10)
{
return boost::beast::http::token_list{m[boost::beast::http::field::connection]}.exists(
"keep-alive");
}
return !boost::beast::http::token_list{m[boost::beast::http::field::connection]}.exists(
"close");
}

View File

@@ -44,7 +44,7 @@ public:
: work_(boost::asio::make_work_guard(ios_))
{
threads_.reserve(concurrency);
while (concurrency--)
while ((concurrency--) != 0u)
threads_.emplace_back([&] { ios_.run(); });
}

View File

@@ -32,9 +32,13 @@ type_name()
if (std::is_volatile<TR>::value)
name += " volatile";
if (std::is_lvalue_reference<T>::value)
{
name += "&";
}
else if (std::is_rvalue_reference<T>::value)
{
name += "&&";
}
return name;
}

View File

@@ -50,7 +50,7 @@ private:
virtual void
on_case_end() override
{
if (m_case.tests.size() > 0)
if (!m_case.tests.empty())
m_suite.insert(std::move(m_case));
}

View File

@@ -198,8 +198,10 @@ runner::run_if(FwdIter first, FwdIter last, Pred pred)
{
bool failed(false);
for (; first != last; ++first)
{
if (pred(*first))
failed = run(*first) || failed;
}
return failed;
}
@@ -219,8 +221,10 @@ runner::run_each_if(SequenceContainer const& c, Pred pred)
{
bool failed(false);
for (auto const& s : c)
{
if (pred(s))
failed = run(s) || failed;
}
return failed;
}

View File

@@ -309,7 +309,7 @@ private:
run() = 0;
void
propagate_abort();
propagate_abort() const;
template <class = void>
void
@@ -486,9 +486,13 @@ suite::unexpected(Condition shouldBeFalse, String const& reason)
{
bool const b = static_cast<bool>(shouldBeFalse);
if (!b)
{
pass();
}
else
{
fail(reason);
}
return !b;
}
@@ -522,7 +526,7 @@ suite::fail(String const& reason, char const* file, int line)
}
inline void
suite::propagate_abort()
suite::propagate_abort() const
{
if (abort_ && aborted_)
BOOST_THROW_EXCEPTION(abort_exception());

View File

@@ -13,13 +13,13 @@ enum Severity {
kAll = 0,
kTrace = kAll,
kDebug,
kInfo,
kWarning,
kError,
kFatal,
kDebug = 1,
kInfo = 2,
kWarning = 3,
kError = 4,
kFatal = 5,
kDisabled,
kDisabled = 6,
kNone = kDisabled
};
} // namespace severities
@@ -109,12 +109,12 @@ public:
};
#ifndef __INTELLISENSE__
static_assert(std::is_default_constructible<Sink>::value == false, "");
static_assert(std::is_copy_constructible<Sink>::value == false, "");
static_assert(std::is_move_constructible<Sink>::value == false, "");
static_assert(std::is_copy_assignable<Sink>::value == false, "");
static_assert(std::is_move_assignable<Sink>::value == false, "");
static_assert(std::is_nothrow_destructible<Sink>::value == true, "");
static_assert(!std::is_default_constructible_v<Sink>, "");
static_assert(!std::is_copy_constructible_v<Sink>, "");
static_assert(!std::is_move_constructible_v<Sink>, "");
static_assert(!std::is_copy_assignable_v<Sink>, "");
static_assert(!std::is_move_assignable_v<Sink>, "");
static_assert(std::is_nothrow_destructible_v<Sink>, "");
#endif
/** Returns a Sink which does nothing. */
@@ -165,12 +165,12 @@ public:
};
#ifndef __INTELLISENSE__
static_assert(std::is_default_constructible<ScopedStream>::value == false, "");
static_assert(std::is_copy_constructible<ScopedStream>::value == true, "");
static_assert(std::is_move_constructible<ScopedStream>::value == true, "");
static_assert(std::is_copy_assignable<ScopedStream>::value == false, "");
static_assert(std::is_move_assignable<ScopedStream>::value == false, "");
static_assert(std::is_nothrow_destructible<ScopedStream>::value == true, "");
static_assert(!std::is_default_constructible_v<ScopedStream>, "");
static_assert(std::is_copy_constructible_v<ScopedStream>, "");
static_assert(std::is_move_constructible_v<ScopedStream>, "");
static_assert(!std::is_copy_assignable_v<ScopedStream>, "");
static_assert(!std::is_move_assignable_v<ScopedStream>, "");
static_assert(std::is_nothrow_destructible_v<ScopedStream>, "");
#endif
//--------------------------------------------------------------------------
@@ -247,12 +247,12 @@ public:
};
#ifndef __INTELLISENSE__
static_assert(std::is_default_constructible<Stream>::value == true, "");
static_assert(std::is_copy_constructible<Stream>::value == true, "");
static_assert(std::is_move_constructible<Stream>::value == true, "");
static_assert(std::is_copy_assignable<Stream>::value == false, "");
static_assert(std::is_move_assignable<Stream>::value == false, "");
static_assert(std::is_nothrow_destructible<Stream>::value == true, "");
static_assert(std::is_default_constructible_v<Stream>, "");
static_assert(std::is_copy_constructible_v<Stream>, "");
static_assert(std::is_move_constructible_v<Stream>, "");
static_assert(!std::is_copy_assignable_v<Stream>, "");
static_assert(!std::is_move_assignable_v<Stream>, "");
static_assert(std::is_nothrow_destructible_v<Stream>, "");
#endif
//--------------------------------------------------------------------------
@@ -330,12 +330,12 @@ public:
};
#ifndef __INTELLISENSE__
static_assert(std::is_default_constructible<Journal>::value == false, "");
static_assert(std::is_copy_constructible<Journal>::value == true, "");
static_assert(std::is_move_constructible<Journal>::value == true, "");
static_assert(std::is_copy_assignable<Journal>::value == true, "");
static_assert(std::is_move_assignable<Journal>::value == true, "");
static_assert(std::is_nothrow_destructible<Journal>::value == true, "");
static_assert(!std::is_default_constructible_v<Journal>, "");
static_assert(std::is_copy_constructible_v<Journal>, "");
static_assert(std::is_move_constructible_v<Journal>, "");
static_assert(std::is_copy_assignable_v<Journal>, "");
static_assert(std::is_move_assignable_v<Journal>, "");
static_assert(std::is_nothrow_destructible_v<Journal>, "");
#endif
//------------------------------------------------------------------------------

View File

@@ -27,7 +27,7 @@ struct Zero
};
namespace {
static constexpr Zero zero{};
constexpr Zero zero{};
} // namespace
/** Default implementation of signum calls the method on the class. */

View File

@@ -89,7 +89,7 @@ parsePreamble(Slice& s, std::error_code& ec)
p.length = s[0];
s += 1;
if (p.length & 0x80)
if ((p.length & 0x80) != 0u)
{ // Long form length:
std::size_t const cnt = p.length & 0x7F;

View File

@@ -34,9 +34,9 @@ template <typename Ret_t, typename... Args_t>
class ClosureCounter
{
private:
std::mutex mutable mutex_{};
std::condition_variable allClosuresDoneCond_{}; // guard with mutex_
bool waitForClosures_{false}; // guard with mutex_
std::mutex mutable mutex_;
std::condition_variable allClosuresDoneCond_; // guard with mutex_
bool waitForClosures_{false}; // guard with mutex_
std::atomic<int> closureCount_{0};
// Increment the count.

View File

@@ -20,7 +20,7 @@ struct PeerReservation final
{
public:
PublicKey nodeId;
std::string description{};
std::string description = {}; // NOLINT(readability-redundant-member-init)
auto
toJson() const -> Json::Value;
@@ -68,7 +68,7 @@ public:
contains(PublicKey const& nodeId)
{
std::lock_guard const lock(this->mutex_);
return table_.find({nodeId}) != table_.end();
return table_.contains({.nodeId = nodeId, .description = {}});
}
// Because `ApplicationImp` has two-phase initialization, so must we.

View File

@@ -1,12 +1,11 @@
#pragma once
#include <ostream>
#include <xrpl/json/json_writer.h>
#include <string>
namespace Json {
class Value;
/** Writes a Json::Value to an std::string. */
std::string
to_string(Value const&);
@@ -15,8 +14,4 @@ to_string(Value const&);
std::string
pretty(Value const&);
/** Output using the StyledStreamWriter. @see Json::operator>>(). */
std::ostream&
operator<<(std::ostream&, Value const& root);
} // namespace Json

View File

@@ -75,10 +75,12 @@ public:
doValidatedLedger(std::shared_ptr<ReadView const> const& lastValidatedLedger)
{
if (needValidatedLedger(lastValidatedLedger->seq()))
{
doValidatedLedger(
lastValidatedLedger->seq(),
getEnabledAmendments(*lastValidatedLedger),
getMajorityAmendments(*lastValidatedLedger));
}
}
/** Called to determine whether the amendment logic needs to process

View File

@@ -29,31 +29,31 @@ private:
friend bool
operator<(Key const& lhs, Key const& rhs);
inline friend bool
friend bool
operator>(Key const& lhs, Key const& rhs)
{
return rhs < lhs;
}
inline friend bool
friend bool
operator<=(Key const& lhs, Key const& rhs)
{
return !(lhs > rhs);
}
inline friend bool
friend bool
operator>=(Key const& lhs, Key const& rhs)
{
return !(lhs < rhs);
}
inline friend bool
friend bool
operator==(Key const& lhs, Key const& rhs)
{
return lhs.txId_ == rhs.txId_;
}
inline friend bool
friend bool
operator!=(Key const& lhs, Key const& rhs)
{
return !(lhs == rhs);

View File

@@ -65,7 +65,7 @@ public:
pending(LedgerIndex seq)
{
std::lock_guard const lock(mutex_);
return map_.find(seq) != map_.end();
return map_.contains(seq);
}
/** Check if a ledger should be dispatched

View File

@@ -208,10 +208,10 @@ getAMMOfferStartWithTakerGets(
// Try to reduce the offer size to improve the quality.
// The quality might still not match the targetQuality for a tiny offer.
if (auto amounts = getAmounts(*nTakerGets); Quality{amounts} < targetQuality)
auto amounts = getAmounts(*nTakerGets);
if (Quality{amounts} < targetQuality)
return getAmounts(detail::reduceOffer(amounts.out));
else
return amounts;
return amounts;
}
/** Generate AMM offer starting with takerPays when AMM pool
@@ -275,10 +275,10 @@ getAMMOfferStartWithTakerPays(
// Try to reduce the offer size to improve the quality.
// The quality might still not match the targetQuality for a tiny offer.
if (auto amounts = getAmounts(*nTakerPays); Quality{amounts} < targetQuality)
auto amounts = getAmounts(*nTakerPays);
if (Quality{amounts} < targetQuality)
return getAmounts(detail::reduceOffer(amounts.in));
else
return amounts;
return amounts;
}
/** Generate AMM offer so that either updated Spot Price Quality (SPQ)
@@ -318,9 +318,12 @@ changeSpotPriceQuality(
auto const& a = f;
auto const b = pool.in * (1 + f);
Number const c = pool.in * pool.in - pool.in * pool.out * quality.rate();
if (auto const res = b * b - 4 * a * c; res < 0)
auto const res = b * b - 4 * a * c;
if (res < 0)
{
return std::nullopt; // LCOV_EXCL_LINE
else if (auto const nTakerPaysPropose = (-b + root2(res)) / (2 * a); nTakerPaysPropose > 0)
}
if (auto const nTakerPaysPropose = (-b + root2(res)) / (2 * a); nTakerPaysPropose > 0)
{
auto const nTakerPays = [&]() {
// The fee might make the AMM offer quality less than CLOB
@@ -465,13 +468,11 @@ swapAssetIn(TAmounts<TIn, TOut> const& pool, TIn const& assetIn, std::uint16_t t
return toAmount<TOut>(getAsset(pool.out), swapOut, Number::downward);
}
else
{
return toAmount<TOut>(
getAsset(pool.out),
pool.out - (pool.in * pool.out) / (pool.in + assetIn * feeMult(tfee)),
Number::downward);
}
return toAmount<TOut>(
getAsset(pool.out),
pool.out - (pool.in * pool.out) / (pool.in + assetIn * feeMult(tfee)),
Number::downward);
}
/** Swap assetOut out of the pool and swap in a proportional amount
@@ -533,13 +534,11 @@ swapAssetOut(TAmounts<TIn, TOut> const& pool, TOut const& assetOut, std::uint16_
return toAmount<TIn>(getAsset(pool.in), swapIn, Number::upward);
}
else
{
return toAmount<TIn>(
getAsset(pool.in),
((pool.in * pool.out) / (pool.out - assetOut) - pool.in) / feeMult(tfee),
Number::upward);
}
return toAmount<TIn>(
getAsset(pool.in),
((pool.in * pool.out) / (pool.out - assetOut) - pool.in) / feeMult(tfee),
Number::upward);
}
/** Return square of n.
@@ -623,9 +622,13 @@ getRoundedAsset(Rules const& rules, STAmount const& balance, A const& frac, IsDe
if (!rules.enabled(fixAMMv1_3))
{
if constexpr (std::is_same_v<A, STAmount>)
{
return multiply(balance, frac, balance.asset());
}
else
{
return toSTAmount(balance.asset(), balance * frac);
}
}
auto const rm = detail::getAssetRounding(isDeposit);
return multiply(balance, frac, rm);

View File

@@ -189,7 +189,7 @@ forEachItem(
AccountID const& id,
std::function<void(std::shared_ptr<SLE const> const&)> const& f)
{
return forEachItem(view, keylet::ownerDir(id), f);
forEachItem(view, keylet::ownerDir(id), f);
}
/** Iterate all items after an item in an owner directory.

View File

@@ -121,15 +121,6 @@ canTransfer(
[[nodiscard]] TER
canTrade(ReadView const& view, Asset const& asset);
/** Convenience to combine canTrade/Transfer. Returns tesSUCCESS if Asset is Issue.
*/
[[nodiscard]] TER
canMPTTradeAndTransfer(
ReadView const& v,
Asset const& asset,
AccountID const& from,
AccountID const& to);
//------------------------------------------------------------------------------
//
// Empty holding operations (MPT-specific)
@@ -236,4 +227,17 @@ issuerFundsToSelfIssue(ReadView const& view, MPTIssue const& issue);
void
issuerSelfDebitHookMPT(ApplyView& view, MPTIssue const& issue, std::uint64_t amount);
//------------------------------------------------------------------------------
//
// MPT DEX
//
//------------------------------------------------------------------------------
/* Return true if a transaction is allowed for the specified MPT/account. The
* function checks MPTokenIssuance and MPToken objects flags to determine if the
* transaction is allowed.
*/
TER
checkMPTTxAllowed(ReadView const& v, TxType tx, Asset const& asset, AccountID const& accountID);
} // namespace xrpl

View File

@@ -1,6 +1,8 @@
#pragma once
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/UintTypes.h>
namespace xrpl {

View File

@@ -54,15 +54,9 @@ enum class AuthType { StrongAuth, WeakAuth, Legacy };
[[nodiscard]] bool
isGlobalFrozen(ReadView const& view, Asset const& asset);
[[nodiscard]] TER
checkGlobalFrozen(ReadView const& view, Asset const& asset);
[[nodiscard]] bool
isIndividualFrozen(ReadView const& view, AccountID const& account, Asset const& asset);
[[nodiscard]] TER
checkIndividualFrozen(ReadView const& view, AccountID const& account, Asset const& asset);
/**
* isFrozen check is recursive for MPT shares in a vault, descending to
* assets in the vault, up to maxAssetCheckDepth recursion depth. This is

View File

@@ -44,7 +44,7 @@ public:
}
bool
isSecure()
isSecure() const
{
return mSecure;
}
@@ -126,7 +126,9 @@ public:
async_shutdown(ShutdownHandler handler)
{
if (isSecure())
{
mSocket->async_shutdown(handler);
}
else
{
error_code ec;
@@ -147,9 +149,13 @@ public:
async_read_some(Seq const& buffers, Handler handler)
{
if (isSecure())
{
mSocket->async_read_some(buffers, handler);
}
else
{
PlainSocket().async_read_some(buffers, handler);
}
}
template <typename Seq, typename Condition, typename Handler>
@@ -157,9 +163,13 @@ public:
async_read_until(Seq const& buffers, Condition condition, Handler handler)
{
if (isSecure())
{
boost::asio::async_read_until(*mSocket, buffers, condition, handler);
}
else
{
boost::asio::async_read_until(PlainSocket(), buffers, condition, handler);
}
}
template <typename Allocator, typename Handler>
@@ -170,9 +180,13 @@ public:
Handler handler)
{
if (isSecure())
{
boost::asio::async_read_until(*mSocket, buffers, delim, handler);
}
else
{
boost::asio::async_read_until(PlainSocket(), buffers, delim, handler);
}
}
template <typename Allocator, typename MatchCondition, typename Handler>
@@ -183,9 +197,13 @@ public:
Handler handler)
{
if (isSecure())
{
boost::asio::async_read_until(*mSocket, buffers, cond, handler);
}
else
{
boost::asio::async_read_until(PlainSocket(), buffers, cond, handler);
}
}
template <typename Buf, typename Handler>
@@ -193,9 +211,13 @@ public:
async_write(Buf const& buffers, Handler handler)
{
if (isSecure())
{
boost::asio::async_write(*mSocket, buffers, handler);
}
else
{
boost::asio::async_write(PlainSocket(), buffers, handler);
}
}
template <typename Allocator, typename Handler>
@@ -203,9 +225,13 @@ public:
async_write(boost::asio::basic_streambuf<Allocator>& buffers, Handler handler)
{
if (isSecure())
{
boost::asio::async_write(*mSocket, buffers, handler);
}
else
{
boost::asio::async_write(PlainSocket(), buffers, handler);
}
}
template <typename Buf, typename Condition, typename Handler>
@@ -213,9 +239,13 @@ public:
async_read(Buf const& buffers, Condition cond, Handler handler)
{
if (isSecure())
{
boost::asio::async_read(*mSocket, buffers, cond, handler);
}
else
{
boost::asio::async_read(PlainSocket(), buffers, cond, handler);
}
}
template <typename Allocator, typename Condition, typename Handler>
@@ -223,9 +253,13 @@ public:
async_read(boost::asio::basic_streambuf<Allocator>& buffers, Condition cond, Handler handler)
{
if (isSecure())
{
boost::asio::async_read(*mSocket, buffers, cond, handler);
}
else
{
boost::asio::async_read(PlainSocket(), buffers, cond, handler);
}
}
template <typename Buf, typename Handler>
@@ -233,9 +267,13 @@ public:
async_read(Buf const& buffers, Handler handler)
{
if (isSecure())
{
boost::asio::async_read(*mSocket, buffers, handler);
}
else
{
boost::asio::async_read(PlainSocket(), buffers, handler);
}
}
template <typename Seq, typename Handler>
@@ -243,9 +281,13 @@ public:
async_write_some(Seq const& buffers, Handler handler)
{
if (isSecure())
{
mSocket->async_write_some(buffers, handler);
}
else
{
PlainSocket().async_write_some(buffers, handler);
}
}
protected:

View File

@@ -30,8 +30,10 @@ public:
registerSSLCerts(ssl_context_, ec, j_);
if (ec && sslVerifyDir.empty())
{
Throw<std::runtime_error>(boost::str(
boost::format("Failed to set_default_verify_paths: %s") % ec.message()));
}
}
else
{
@@ -43,8 +45,10 @@ public:
ssl_context_.add_verify_path(sslVerifyDir, ec);
if (ec)
{
Throw<std::runtime_error>(
boost::str(boost::format("Failed to add verify path: %s") % ec.message()));
}
}
}

View File

@@ -22,11 +22,11 @@ enum {
/** Return codes from Backend operations. */
enum Status {
ok,
notFound,
dataCorrupt,
unknown,
backendError,
ok = 0,
notFound = 1,
dataCorrupt = 2,
unknown = 3,
backendError = 4,
customCode = 100
};

View File

@@ -113,9 +113,11 @@ nodeobject_decompress(void const* in, std::size_t in_size, BufferFactory&& bf)
{
auto const hs = field<std::uint16_t>::size; // Mask
if (in_size < hs + 32)
{
Throw<std::runtime_error>(
"nodeobject codec v1: short inner node size: " + std::string("in_size = ") +
std::to_string(in_size) + " hs = " + std::to_string(hs));
}
istream is(p, in_size);
std::uint16_t mask = 0;
read<std::uint16_t>(is, mask); // Mask
@@ -136,10 +138,12 @@ nodeobject_decompress(void const* in, std::size_t in_size, BufferFactory&& bf)
if (mask & bit)
{
if (in_size < 32)
{
Throw<std::runtime_error>(
"nodeobject codec v1: short inner node subsize: " +
std::string("in_size = ") + std::to_string(in_size) +
" i = " + std::to_string(i));
}
std::memcpy(os.data(32), is(32), 32);
in_size -= 32;
}
@@ -149,16 +153,20 @@ nodeobject_decompress(void const* in, std::size_t in_size, BufferFactory&& bf)
}
}
if (in_size > 0)
{
Throw<std::runtime_error>(
"nodeobject codec v1: long inner node, in_size = " + std::to_string(in_size));
}
break;
}
case 3: // full v1 inner node
{
if (in_size != 16 * 32) // hashes
if (in_size != 16 * 32)
{ // hashes
Throw<std::runtime_error>(
"nodeobject codec v1: short full inner node, in_size = " +
std::to_string(in_size));
}
istream is(p, in_size);
result.second = 525;
void* const out = bf(result.second);
@@ -214,7 +222,7 @@ nodeobject_compress(void const* in, std::size_t in_size, BufferFactory&& bf)
void const* const h = is(32);
if (std::memcmp(h, zero32(), 32) == 0)
continue;
std::memcpy(vh.data() + 32 * n, h, 32);
std::memcpy(vh.data() + (32 * n), h, 32);
mask |= bit;
++n;
}
@@ -225,7 +233,7 @@ nodeobject_compress(void const* in, std::size_t in_size, BufferFactory&& bf)
auto const type = 2U;
auto const vs = size_varint(type);
result.second = vs + field<std::uint16_t>::size + // mask
n * 32; // hashes
(n * 32); // hashes
std::uint8_t* out = reinterpret_cast<std::uint8_t*>(bf(result.second));
result.first = out;
ostream os(out, result.second);
@@ -237,7 +245,7 @@ nodeobject_compress(void const* in, std::size_t in_size, BufferFactory&& bf)
// 3 = full v1 inner node
auto const type = 3U;
auto const vs = size_varint(type);
result.second = vs + n * 32; // hashes
result.second = vs + (n * 32); // hashes
std::uint8_t* out = reinterpret_cast<std::uint8_t*>(bf(result.second));
result.first = out;
ostream os(out, result.second);

View File

@@ -42,8 +42,10 @@ read_varint(void const* buf, std::size_t buflen, std::size_t& t)
std::uint8_t const* p = reinterpret_cast<std::uint8_t const*>(buf);
std::size_t n = 0;
while (p[n] & 0x80)
{
if (++n >= buflen)
return 0;
}
if (++n > buflen)
return 0;
// Special case for 0

View File

@@ -148,11 +148,17 @@ toAmount(Asset const& asset, Number const& n, Number::rounding_mode mode = Numbe
Number::setround(mode);
if constexpr (std::is_same_v<IOUAmount, T>)
{
return IOUAmount(n);
}
else if constexpr (std::is_same_v<XRPAmount, T>)
{
return XRPAmount(static_cast<std::int64_t>(n));
}
else if constexpr (std::is_same_v<MPTAmount, T>)
{
return MPTAmount(static_cast<std::int64_t>(n));
}
else if constexpr (std::is_same_v<STAmount, T>)
{
if (isXRP(asset))
@@ -171,11 +177,17 @@ T
toMaxAmount(Asset const& asset)
{
if constexpr (std::is_same_v<IOUAmount, T>)
{
return IOUAmount(STAmount::cMaxValue, STAmount::cMaxOffset);
}
else if constexpr (std::is_same_v<XRPAmount, T>)
{
return XRPAmount(static_cast<std::int64_t>(STAmount::cMaxNativeN));
}
else if constexpr (std::is_same_v<MPTAmount, T>)
{
return MPTAmount(maxMPTokenAmount);
}
else if constexpr (std::is_same_v<STAmount, T>)
{
return asset.visit(
@@ -204,13 +216,21 @@ Asset
getAsset(T const& amt)
{
if constexpr (std::is_same_v<IOUAmount, T>)
{
return noIssue();
}
else if constexpr (std::is_same_v<XRPAmount, T>)
{
return xrpIssue();
}
else if constexpr (std::is_same_v<MPTAmount, T>)
{
return noMPT();
}
else if constexpr (std::is_same_v<STAmount, T>)
{
return amt.asset();
}
else
{
constexpr bool alwaysFalse = !std::is_same_v<T, T>;
@@ -223,13 +243,21 @@ constexpr T
get(STAmount const& a)
{
if constexpr (std::is_same_v<IOUAmount, T>)
{
return a.iou();
}
else if constexpr (std::is_same_v<XRPAmount, T>)
{
return a.xrp();
}
else if constexpr (std::is_same_v<MPTAmount, T>)
{
return a.mpt();
}
else if constexpr (std::is_same_v<STAmount, T>)
{
return a;
}
else
{
constexpr bool alwaysFalse = !std::is_same_v<T, T>;

View File

@@ -221,9 +221,13 @@ operator==(Asset const& lhs, Asset const& rhs)
return std::visit(
[&]<typename TLhs, typename TRhs>(TLhs const& issLhs, TRhs const& issRhs) {
if constexpr (std::is_same_v<TLhs, TRhs>)
{
return issLhs == issRhs;
}
else
{
return false;
}
},
lhs.issue_,
rhs.issue_);
@@ -235,11 +239,17 @@ operator<=>(Asset const& lhs, Asset const& rhs)
return std::visit(
[]<ValidIssueType TLhs, ValidIssueType TRhs>(TLhs const& lhs_, TRhs const& rhs_) {
if constexpr (std::is_same_v<TLhs, TRhs>)
{
return std::weak_ordering(lhs_ <=> rhs_);
}
else if constexpr (is_issue_v<TLhs> && is_mptissue_v<TRhs>)
{
return std::weak_ordering::greater;
}
else
{
return std::weak_ordering::less;
}
},
lhs.issue_,
rhs.issue_);
@@ -267,11 +277,17 @@ equalTokens(Asset const& lhs, Asset const& rhs)
return std::visit(
[&]<typename TLhs, typename TRhs>(TLhs const& issLhs, TRhs const& issRhs) {
if constexpr (std::is_same_v<TLhs, Issue> && std::is_same_v<TRhs, Issue>)
{
return issLhs.currency == issRhs.currency;
}
else if constexpr (std::is_same_v<TLhs, MPTIssue> && std::is_same_v<TRhs, MPTIssue>)
{
return issLhs.getMptID() == issRhs.getMptID();
}
else
{
return false;
}
},
lhs.issue_,
rhs.issue_);
@@ -292,9 +308,6 @@ validJSONAsset(Json::Value const& jv);
Asset
assetFromJson(Json::Value const& jv);
Json::Value
to_json(Asset const& asset);
inline bool
isConsistent(Asset const& asset)
{

View File

@@ -53,7 +53,7 @@ reversed(Book const& book);
/** Equality comparison. */
/** @{ */
[[nodiscard]] inline constexpr bool
[[nodiscard]] constexpr bool
operator==(Book const& lhs, Book const& rhs)
{
return (lhs.in == rhs.in) && (lhs.out == rhs.out) && (lhs.domain == rhs.domain);
@@ -62,7 +62,7 @@ operator==(Book const& lhs, Book const& rhs)
/** Strict weak ordering. */
/** @{ */
[[nodiscard]] inline constexpr std::weak_ordering
[[nodiscard]] constexpr std::weak_ordering
operator<=>(Book const& lhs, Book const& rhs)
{
if (auto const c{lhs.in <=> rhs.in}; c != 0)

View File

@@ -107,8 +107,8 @@ validFeatureName(auto fn) -> bool
return true;
}
enum class VoteBehavior : int { Obsolete = -1, DefaultNo = 0, DefaultYes };
enum class AmendmentSupport : int { Retired = -1, Supported = 0, Unsupported };
enum class VoteBehavior : int { Obsolete = -1, DefaultNo = 0, DefaultYes = 1 };
enum class AmendmentSupport : int { Retired = -1, Supported = 0, Unsupported = 1 };
/** All amendments libxrpl knows about. */
std::map<std::string, AmendmentSupport> const&
@@ -375,8 +375,10 @@ void
foreachFeature(FeatureBitset bs, F&& f)
{
for (size_t i = 0; i < bs.size(); ++i)
{
if (bs[i])
f(bitsetIndexToFeature(i));
}
}
#pragma push_macro("XRPL_FEATURE")

View File

@@ -151,7 +151,9 @@ operator bool() const noexcept
inline int
IOUAmount::signum() const noexcept
{
return (mantissa_ < 0) ? -1 : (mantissa_ ? 1 : 0);
if (mantissa_ < 0)
return -1;
return (mantissa_ != 0) ? 1 : 0;
}
inline IOUAmount::exponent_type

View File

@@ -12,8 +12,8 @@ namespace xrpl {
class Issue
{
public:
Currency currency{};
AccountID account{};
Currency currency;
AccountID account;
Issue() = default;
@@ -68,7 +68,7 @@ hash_append(Hasher& h, Issue const& r)
/** Equality comparison. */
/** @{ */
[[nodiscard]] inline constexpr bool
[[nodiscard]] constexpr bool
operator==(Issue const& lhs, Issue const& rhs)
{
return (lhs.currency == rhs.currency) && (isXRP(lhs.currency) || lhs.account == rhs.account);

View File

@@ -19,7 +19,7 @@ struct LedgerHeader
//
LedgerIndex seq = 0;
NetClock::time_point parentCloseTime = {};
NetClock::time_point parentCloseTime;
//
// For closed ledgers
@@ -49,7 +49,7 @@ struct LedgerHeader
// closed. For open ledgers, the time the ledger
// will close if there's no transactions.
//
NetClock::time_point closeTime = {};
NetClock::time_point closeTime;
};
// ledger close flags

View File

@@ -109,7 +109,9 @@ operator bool() const noexcept
constexpr int
MPTAmount::signum() const noexcept
{
return (value_ < 0) ? -1 : (value_ ? 1 : 0);
if (value_ < 0)
return -1;
return (value_ != 0) ? 1 : 0;
}
/** Returns the underlying value. Code SHOULD NOT call this
@@ -141,7 +143,7 @@ mulRatio(MPTAmount const& amt, std::uint32_t num, std::uint32_t den, bool roundU
{
using namespace boost::multiprecision;
if (!den)
if (den == 0u)
Throw<std::runtime_error>("division by zero");
int128_t const amt128(amt.value());

View File

@@ -47,14 +47,14 @@ public:
friend constexpr std::weak_ordering
operator<=>(MPTIssue const& lhs, MPTIssue const& rhs);
bool
native() const
static bool
native()
{
return false;
}
bool
integral() const
static bool
integral()
{
return true;
}
@@ -94,9 +94,9 @@ getMPTIssuer(MPTID const& mptid)
}
// Disallow temporary
inline AccountID const&
AccountID const&
getMPTIssuer(MPTID const&&) = delete;
inline AccountID const&
AccountID const&
getMPTIssuer(MPTID&&) = delete;
inline MPTID

View File

@@ -74,10 +74,14 @@ struct MultiApiJson
{
int count = 0;
for (auto& a : this->val)
{
if (a.isMember(key))
count += 1;
}
return (count == 0 ? none : (count < size ? some : all));
if (count == 0)
return none;
return count < size ? some : all;
}
static constexpr struct visitor_t final

View File

@@ -100,9 +100,13 @@ operator==(PathAsset const& lhs, PathAsset const& rhs)
return std::visit(
[]<ValidPathAsset TLhs, ValidPathAsset TRhs>(TLhs const& lhs_, TRhs const& rhs_) {
if constexpr (std::is_same_v<TLhs, TRhs>)
{
return lhs_ == rhs_;
}
else
{
return false;
}
},
lhs.value(),
rhs.value());

View File

@@ -69,8 +69,8 @@ public:
return buf_;
}
std::size_t
size() const noexcept
static std::size_t
size() noexcept
{
return size_;
}

View File

@@ -281,7 +281,7 @@ public:
double const minVD = static_cast<double>(minVMantissa);
double const maxVD =
expDiff ? maxVMantissa * pow(10, expDiff) : static_cast<double>(maxVMantissa);
(expDiff != 0) ? maxVMantissa * pow(10, expDiff) : static_cast<double>(maxVMantissa);
// maxVD and minVD are scaled so they have the same exponents. Dividing
// cancels out the exponents, so we only need to deal with the (scaled)

View File

@@ -1,6 +1,7 @@
#pragma once
#include <xrpl/json/json_value.h>
#include <xrpl/protocol/ErrorCodes.h>
namespace xrpl {

View File

@@ -42,13 +42,13 @@ private:
public:
using value_type = STAmount;
static int const cMinOffset = -96;
static int const cMaxOffset = 80;
static constexpr int cMinOffset = -96;
static constexpr int cMaxOffset = 80;
// Maximum native value supported by the code
constexpr static std::uint64_t cMinValue = 1'000'000'000'000'000ull;
static_assert(isPowerOfTen(cMinValue));
constexpr static std::uint64_t cMaxValue = cMinValue * 10 - 1;
constexpr static std::uint64_t cMaxValue = (cMinValue * 10) - 1;
static_assert(cMaxValue == 9'999'999'999'999'999ull);
constexpr static std::uint64_t cMaxNative = 9'000'000'000'000'000'000ull;
@@ -359,9 +359,13 @@ inline STAmount::STAmount(IOUAmount const& amount, Issue const& issue)
: mAsset(issue), mOffset(amount.exponent()), mIsNegative(amount < beast::zero)
{
if (mIsNegative)
{
mValue = unsafe_cast<std::uint64_t>(-amount.mantissa());
}
else
{
mValue = unsafe_cast<std::uint64_t>(amount.mantissa());
}
canonicalize();
}
@@ -370,9 +374,13 @@ inline STAmount::STAmount(MPTAmount const& amount, MPTIssue const& mptIssue)
: mAsset(mptIssue), mOffset(0), mIsNegative(amount < beast::zero)
{
if (mIsNegative)
{
mValue = unsafe_cast<std::uint64_t>(-amount.value());
}
else
{
mValue = unsafe_cast<std::uint64_t>(amount.value());
}
canonicalize();
}
@@ -476,7 +484,9 @@ STAmount::getIssuer() const
inline int
STAmount::signum() const noexcept
{
return mValue ? (mIsNegative ? -1 : 1) : 0;
if (mValue == 0u)
return 0;
return mIsNegative ? -1 : 1;
}
inline STAmount

View File

@@ -95,7 +95,7 @@ STBlob::size() const
inline std::uint8_t const*
STBlob::data() const
{
return reinterpret_cast<std::uint8_t const*>(value_.data());
return value_.data();
}
inline STBlob&

View File

@@ -11,7 +11,7 @@ namespace xrpl {
class STCurrency final : public STBase
{
private:
Currency currency_{};
Currency currency_;
public:
using value_type = Currency;

View File

@@ -704,7 +704,7 @@ class STObject::FieldErr : public std::runtime_error
template <class T>
STObject::Proxy<T>::Proxy(STObject* st, TypedField<T> const* f) : st_(st), f_(f)
{
if (st_->mType)
if (st_->mType != nullptr)
{
// STObject has associated template
if (!st_->peekAtPField(*f_))
@@ -770,9 +770,13 @@ STObject::Proxy<T>::assign(U&& u)
}
T* t = nullptr;
if (style_ == soeINVALID)
{
t = dynamic_cast<T*>(st_->getPField(*f_, true));
}
else
{
t = dynamic_cast<T*>(st_->makeFieldPresent(*f_));
}
XRPL_ASSERT(t, "xrpl::STObject::Proxy::assign : type cast succeeded");
*t = std::forward<U>(u);
}
@@ -858,9 +862,13 @@ STObject::OptionalProxy<T>::operator=(
-> OptionalProxy&
{
if (v)
{
this->assign(std::move(*v));
}
else
{
disengage();
}
return *this;
}
@@ -869,9 +877,13 @@ auto
STObject::OptionalProxy<T>::operator=(optional_type const& v) -> OptionalProxy&
{
if (v)
{
this->assign(*v);
}
else
{
disengage();
}
return *this;
}
@@ -903,9 +915,13 @@ STObject::OptionalProxy<T>::disengage()
if (this->style_ == soeREQUIRED || this->style_ == soeDEFAULT)
Throw<STObject::FieldErr>("Template field error '" + this->f_->getName() + "'");
if (this->style_ == soeINVALID)
{
this->st_->delField(*this->f_);
}
else
{
this->st_->makeFieldAbsent(*this->f_);
}
}
template <class T>
@@ -1058,9 +1074,11 @@ STObject::at(TypedField<T> const& f) const
{
auto const b = peekAtPField(f);
if (!b)
{
// This is a free object (no constraints)
// with no template
Throw<STObject::FieldErr>("Missing field: " + f.getName());
}
if (auto const u = dynamic_cast<T const*>(b))
return u->value();
@@ -1138,9 +1156,13 @@ STObject::setFieldH160(SField const& field, base_uint<160, Tag> const& v)
using Bits = STBitString<160>;
if (auto cf = dynamic_cast<Bits*>(rf))
{
cf->setValue(v);
}
else
{
Throw<std::runtime_error>("Wrong field type");
}
}
inline bool
@@ -1188,8 +1210,10 @@ STObject::getFieldByConstRef(SField const& field, V const& empty) const
SerializedTypeID const id = rf->getSType();
if (id == STI_NOTPRESENT)
{
// NOLINTNEXTLINE(bugprone-return-const-ref-from-parameter)
return empty; // optional field not present
}
T const* cf = dynamic_cast<T const*>(rf);

View File

@@ -36,7 +36,7 @@ class STValidation final : public STObject, public CountedObject<STValidation>
// that use manifests this will be derived from the master public key.
NodeID const nodeID_;
NetClock::time_point seenTime_ = {};
NetClock::time_point seenTime_;
public:
/** Construct a STValidation from a peer from serialized data.

View File

@@ -148,7 +148,7 @@ STVector256::size() const
inline void
STVector256::resize(std::size_t n)
{
return mValue.resize(n);
mValue.resize(n);
}
inline bool
@@ -220,7 +220,7 @@ STVector256::erase(std::vector<uint256>::iterator position)
inline void
STVector256::clear() noexcept
{
return mValue.clear();
mValue.clear();
}
} // namespace xrpl

View File

@@ -85,10 +85,10 @@ public:
}
};
inline bool
bool
operator==(SecretKey const& lhs, SecretKey const& rhs) = delete;
inline bool
bool
operator!=(SecretKey const& lhs, SecretKey const& rhs) = delete;
//------------------------------------------------------------------------------

View File

@@ -33,7 +33,7 @@ public:
{
mData.resize(size);
if (size)
if (size != 0u)
{
XRPL_ASSERT(data, "xrpl::Serializer::Serializer(void const*) : non-null input");
std::memcpy(mData.data(), data, size);

View File

@@ -267,7 +267,9 @@ public:
constexpr int
signum() const noexcept
{
return (value_ < 0) ? -1 : (value_ ? 1 : 0);
if (value_ < 0)
return -1;
return value_ ? 1 : 0;
}
/** Returns the number of drops */

View File

@@ -149,7 +149,9 @@ public:
constexpr int
signum() const noexcept
{
return (drops_ < 0) ? -1 : (drops_ ? 1 : 0);
if (drops_ < 0)
return -1;
return (drops_ != 0) ? 1 : 0;
}
/** Returns the number of drops */
@@ -262,7 +264,7 @@ mulRatio(XRPAmount const& amt, std::uint32_t num, std::uint32_t den, bool roundU
{
using namespace boost::multiprecision;
if (!den)
if (den == 0u)
Throw<std::runtime_error>("division by zero");
int128_t const amt128(amt.drops());

View File

@@ -112,9 +112,13 @@ private:
construct(Args&&... args)
{
if constexpr (sizeof(T) > max_size)
{
p_ = new T(std::forward<Args>(args)...);
}
else
{
p_ = new (&d_) T(std::forward<Args>(args)...);
}
}
/** Construct requested Serializable Type according to id.

View File

@@ -33,7 +33,7 @@ carrying_mul(std::uint64_t a, std::uint64_t b, std::uint64_t carry)
{
unsigned __int128 const x = a;
unsigned __int128 const y = b;
unsigned __int128 const c = x * y + carry;
unsigned __int128 const c = (x * y) + carry;
return {c & 0xffff'ffff'ffff'ffff, c >> 64};
}
@@ -64,13 +64,13 @@ inplace_bigint_add(std::span<std::uint64_t> a, std::uint64_t b)
for (auto& v : a.subspan(1))
{
if (!carry)
if (carry == 0u)
{
return TokenCodecErrc::success;
}
std::tie(v, carry) = carrying_add(v, 1);
}
if (carry)
if (carry != 0u)
{
return TokenCodecErrc::overflowAdd;
}
@@ -105,7 +105,7 @@ inplace_bigint_mul(std::span<std::uint64_t> a, std::uint64_t b)
[[nodiscard]] inline std::uint64_t
inplace_bigint_div_rem(std::span<uint64_t> numerator, std::uint64_t divisor)
{
if (numerator.size() == 0)
if (numerator.empty())
{
// should never happen, but if it does then it seems natural to define
// the a null set of numbers to be zero, so the remainder is also zero.

View File

@@ -177,12 +177,12 @@ public:
}
private:
inline void
void
erase(std::false_type)
{
}
inline void
void
erase(std::true_type)
{
secure_erase(&h_, sizeof(h_));

View File

@@ -4,42 +4,33 @@ This directory contains auto-generated C++ wrapper classes for XRP Ledger protoc
## Generated Files
The files in this directory are automatically generated at **CMake configure time** from macro definition files:
The files in this directory are generated from macro definition files:
- **Transaction classes** (in `transactions/`): Generated from `include/xrpl/protocol/detail/transactions.macro` by `scripts/generate_tx_classes.py`
- **Ledger entry classes** (in `ledger_entries/`): Generated from `include/xrpl/protocol/detail/ledger_entries.macro` by `scripts/generate_ledger_classes.py`
- **Transaction classes** (in `transactions/`): Generated from `include/xrpl/protocol/detail/transactions.macro` by `cmake/scripts/codegen/generate_tx_classes.py`
- **Ledger entry classes** (in `ledger_entries/`): Generated from `include/xrpl/protocol/detail/ledger_entries.macro` by `cmake/scripts/codegen/generate_ledger_classes.py`
## Generation Process
The generation happens automatically when you **configure** the project (not during build). When you run CMake, the system:
Generation requires a one-time setup step to create a virtual environment
and install Python dependencies, followed by running the generation target:
1. Creates a Python virtual environment in the build directory (`codegen_venv`)
2. Installs Python dependencies from `scripts/requirements.txt` into the venv (only if needed)
3. Runs the Python generation scripts using the venv Python interpreter
4. Parses the macro files to extract type definitions
5. Generates type-safe C++ wrapper classes using Mako templates
6. Places the generated headers in this directory
```bash
cmake --build . --target setup_code_gen # create venv and install dependencies (once)
cmake --build . --target code_gen # generate code
```
### When Regeneration Happens
The code is regenerated when:
- You run CMake configure for the first time
- The Python virtual environment doesn't exist
- `scripts/requirements.txt` has been modified
To force regeneration, delete the build directory and reconfigure.
By default, `CODEGEN_VENV_DIR` points to `.venv` in the project root. The
`setup_code_gen` target creates a venv there and installs the required packages.
The `code_gen` target then uses the venv's Python interpreter to run generation.
### Python Dependencies
The code generation requires the following Python packages (automatically installed):
The code generation requires the following Python packages (installed by `setup_code_gen`):
- `pcpp` - C preprocessor for Python
- `pyparsing` - Parser combinator library
- `Mako` - Template engine
These are isolated in a virtual environment and won't affect your system Python installation.
## Version Control
The generated `.h` files **are checked into version control**. This means:
@@ -50,15 +41,15 @@ The generated `.h` files **are checked into version control**. This means:
## Modifying Generated Code
**Do not manually edit generated files.** Any changes will be overwritten the next time CMake configure runs.
**Do not manually edit generated files.** Any changes will be overwritten the next time `code_gen` is run.
To modify the generated classes:
- Edit the macro files in `include/xrpl/protocol/detail/`
- Edit the Mako templates in `scripts/templates/`
- Edit the generation scripts in `scripts/`
- Update Python dependencies in `scripts/requirements.txt`
- Run CMake configure to regenerate
- Edit the Mako templates in `cmake/scripts/codegen/templates/`
- Edit the generation scripts in `cmake/scripts/codegen/`
- Update Python dependencies in `cmake/scripts/codegen/requirements.txt`
- Run `cmake --build . --target code_gen` to regenerate
## Adding Common Fields
@@ -73,7 +64,7 @@ Base classes:
Templates (update to pass required common fields to base class constructors):
- `scripts/templates/Transaction.h.mako`
- `scripts/templates/LedgerEntry.h.mako`
- `cmake/scripts/codegen/templates/Transaction.h.mako`
- `cmake/scripts/codegen/templates/LedgerEntry.h.mako`
These files are **not auto-generated** and must be updated by hand.

View File

@@ -22,7 +22,7 @@ struct Entry : public beast::List<Entry>::Node
@param now Construction time of Entry.
*/
explicit Entry(clock_type::time_point const now)
: refcount(0), local_balance(now), remote_balance(0), lastWarningTime(), whenExpires()
: refcount(0), local_balance(now), remote_balance(0)
{
}

View File

@@ -18,7 +18,7 @@ struct Import
};
// Dummy argument required for zero-copy construction
Import(int = 0) : whenExpires()
Import(int = 0)
{
}

View File

@@ -352,7 +352,9 @@ public:
iter = importTable_.erase(iter);
}
else
{
++iter;
}
}
}
@@ -506,7 +508,7 @@ public:
//--------------------------------------------------------------------------
void
static void
writeList(
clock_type::time_point const now,
beast::PropertyStream::Set& items,

View File

@@ -60,8 +60,8 @@ public:
return clusterTxnLoadFee_;
}
std::uint32_t
getLoadBase() const
static std::uint32_t
getLoadBase()
{
return lftNormalFee;
}

View File

@@ -73,7 +73,7 @@ public:
using clock_type = beast::abstract_clock<std::chrono::steady_clock>;
enum class FailHard : unsigned char { no, yes };
static inline FailHard
static FailHard
doFailHard(bool noMeansDont)
{
return noMeansDont ? FailHard::yes : FailHard::no;

View File

@@ -219,10 +219,12 @@ void
BaseHTTPPeer<Handler, Impl>::close()
{
if (!strand_.running_in_this_thread())
{
return post(
strand_,
std::bind(
(void (BaseHTTPPeer::*)(void))&BaseHTTPPeer::close, impl().shared_from_this()));
}
boost::beast::get_lowest_layer(impl().stream_).close();
}
@@ -398,11 +400,12 @@ BaseHTTPPeer<Handler, Impl>::write(void const* buf, std::size_t bytes)
}())
{
if (!strand_.running_in_this_thread())
{
return post(
strand_,
std::bind(&BaseHTTPPeer::on_write, impl().shared_from_this(), error_code{}, 0));
else
return on_write(error_code{}, 0);
}
return on_write(error_code{}, 0);
}
}
@@ -436,8 +439,10 @@ void
BaseHTTPPeer<Handler, Impl>::complete()
{
if (!strand_.running_in_this_thread())
{
return post(
strand_, std::bind(&BaseHTTPPeer<Handler, Impl>::complete, impl().shared_from_this()));
}
message_ = {};
complete_ = true;
@@ -464,12 +469,14 @@ void
BaseHTTPPeer<Handler, Impl>::close(bool graceful)
{
if (!strand_.running_in_this_thread())
{
return post(
strand_,
std::bind(
(void (BaseHTTPPeer::*)(bool))&BaseHTTPPeer<Handler, Impl>::close,
impl().shared_from_this(),
graceful));
}
complete_ = true;
if (graceful)

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