Compare commits

..

27 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
Alex Kremer
6a0ce46755 chore: Enable most clang-tidy bugprone checks (#6929)
Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
2026-04-14 20:24:21 +00:00
Bart
2f029a2120 refactor: Improve exception handling (#6540) (#6735)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
2026-04-14 17:14:24 +00:00
Zhiyuan Wang
61fbde3a71 refactor: Remove unused notTooManyOffers function from NFTokenUtils (#6737) 2026-04-13 23:18:10 +00:00
Bart
e2e537b3bb fix: Change Tuning::bookOffers minimum limit to 1 (#6812)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
2026-04-10 14:38:46 +00:00
Ed Hennis
a873250019 chore: Make pre-commit line ending conversions work on Windows (#6832) (#6833) 2026-04-10 10:12:52 +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
958 changed files with 12411 additions and 19636 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

@@ -10,26 +10,26 @@ Checks: "-*,
bugprone-chained-comparison,
bugprone-compare-pointer-to-member-virtual-function,
bugprone-copy-constructor-init,
# bugprone-crtp-constructor-accessibility, # has issues
bugprone-crtp-constructor-accessibility,
bugprone-dangling-handle,
bugprone-dynamic-static-initializers,
# bugprone-empty-catch, # has issues
bugprone-empty-catch,
bugprone-fold-init-type,
# bugprone-forward-declaration-namespace, # has issues
# bugprone-inaccurate-erase,
# bugprone-inc-dec-in-conditions,
# bugprone-incorrect-enable-if,
# bugprone-incorrect-roundings,
# bugprone-infinite-loop,
# bugprone-integer-division,
bugprone-forward-declaration-namespace,
bugprone-inaccurate-erase,
bugprone-inc-dec-in-conditions,
bugprone-incorrect-enable-if,
bugprone-incorrect-roundings,
bugprone-infinite-loop,
bugprone-integer-division,
bugprone-lambda-function-name,
# bugprone-macro-parentheses, # has issues
bugprone-macro-parentheses,
bugprone-macro-repeated-side-effects,
bugprone-misplaced-operator-in-strlen-in-alloc,
bugprone-misplaced-pointer-arithmetic-in-alloc,
bugprone-misplaced-widening-cast,
bugprone-move-forwarding-reference,
# bugprone-multi-level-implicit-pointer-conversion, # has issues
bugprone-multi-level-implicit-pointer-conversion,
bugprone-multiple-new-in-one-expression,
bugprone-multiple-statement-macro,
bugprone-no-escape,
@@ -39,13 +39,13 @@ Checks: "-*,
bugprone-pointer-arithmetic-on-polymorphic-object,
bugprone-posix-return,
bugprone-redundant-branch-condition,
# bugprone-reserved-identifier, # has issues
# bugprone-return-const-ref-from-parameter, # has issues
bugprone-reserved-identifier,
bugprone-return-const-ref-from-parameter,
bugprone-shared-ptr-array-mismatch,
bugprone-signal-handler,
bugprone-signed-char-misuse,
bugprone-sizeof-container,
# bugprone-sizeof-expression, # has issues
bugprone-sizeof-expression,
bugprone-spuriously-wake-up-functions,
bugprone-standalone-empty,
bugprone-string-constructor,
@@ -62,7 +62,7 @@ Checks: "-*,
bugprone-suspicious-string-compare,
bugprone-suspicious-stringview-data-usage,
bugprone-swapped-arguments,
# bugprone-switch-missing-default-case, # has issues
bugprone-switch-missing-default-case,
bugprone-terminating-continue,
bugprone-throw-keyword-missing,
bugprone-too-small-loop-variable,
@@ -73,7 +73,7 @@ Checks: "-*,
bugprone-unhandled-self-assignment,
bugprone-unique-ptr-array-mismatch,
bugprone-unsafe-functions,
# bugprone-use-after-move, # has issues
bugprone-use-after-move, # has issues
bugprone-unused-raii,
bugprone-unused-return-value,
bugprone-unused-local-non-trivial-variable,
@@ -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

@@ -17,7 +17,6 @@ repos:
args: [--maxkb=400, --enforce-all]
- id: trailing-whitespace
- id: end-of-file-fixer
- id: mixed-line-ending
- id: check-merge-conflict
args: [--assume-in-merge]
@@ -38,6 +37,7 @@ repos:
rev: c2bc67fe8f8f549cc489e00ba8b45aa18ee713b1 # frozen: v3.8.1
hooks:
- id: prettier
args: [--end-of-line=auto]
- repo: https://github.com/psf/black-pre-commit-mirror
rev: ea488cebbfd88a5f50b8bd95d5c829d0bb76feb8 # frozen: 26.1.0

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

@@ -88,7 +88,6 @@ find_package(ed25519 REQUIRED)
find_package(gRPC REQUIRED)
find_package(LibArchive REQUIRED)
find_package(lz4 REQUIRED)
find_package(mpt-crypto REQUIRED)
find_package(nudb REQUIRED)
find_package(OpenSSL REQUIRED)
find_package(secp256k1 REQUIRED)
@@ -101,7 +100,6 @@ target_link_libraries(
INTERFACE
ed25519::ed25519
lz4::lz4
mpt-crypto::mpt-crypto
OpenSSL::Crypto
OpenSSL::SSL
secp256k1::secp256k1
@@ -134,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

@@ -12,7 +12,6 @@
"protobuf/6.33.5#d96d52ba5baaaa532f47bda866ad87a5%1774467363.12",
"openssl/3.6.1#e6399de266349245a4542fc5f6c71552%1774458290.139",
"nudb/2.0.9#11149c73f8f2baff9a0198fe25971fc7%1774883011.384",
"mpt-crypto/0.3.0-rc1#468344c6855d4aeaa8bd31fb2c403f89%1776358155.918",
"lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1765850143.914",
"libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1765842973.492",
"libbacktrace/cci.20210118#a7691bfccd8caaf66309df196790a5a1%1765842973.03",
@@ -35,7 +34,6 @@
"msys2/cci.latest#d22fe7b2808f5fd34d0a7923ace9c54f%1770657326.649",
"m4/1.4.19#5d7a4994e5875d76faf7acf3ed056036%1774365463.87",
"cmake/4.3.0#b939a42e98f593fb34d3a8c5cc860359%1774439249.183",
"cmake/3.31.10#313d16a1aa16bbdb2ca0792467214b76%1765850153.479",
"b2/5.4.2#ffd6084a119587e70f11cd45d1a386e2%1774439233.447",
"automake/1.16.5#b91b7c384c3deaa9d535be02da14d04f%1755524470.56",
"autoconf/2.71#51077f068e61700d65bb05541ea1e4b0%1731054366.86",
@@ -60,12 +58,6 @@
],
"lz4/[>=1.9.4 <2]": [
"lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504"
],
"openssl/3.5.5": [
"openssl/3.6.1"
],
"openssl/[>=3 <4]": [
"openssl/3.6.1"
]
},
"config_requires": []

View File

@@ -31,7 +31,6 @@ class Xrpl(ConanFile):
"ed25519/2015.03",
"grpc/1.78.1",
"libarchive/3.8.1",
"mpt-crypto/0.3.0-rc1",
"nudb/2.0.9",
"openssl/3.6.1",
"secp256k1/0.7.1",
@@ -215,7 +214,6 @@ class Xrpl(ConanFile):
"grpc::grpc++",
"libarchive::libarchive",
"lz4::lz4",
"mpt-crypto::mpt-crypto",
"nudb::nudb",
"openssl::crypto",
"protobuf::libprotobuf",

View File

@@ -59,7 +59,6 @@ words:
- autobridging
- bimap
- bindir
- blindings
- bookdir
- Bougalis
- Britto
@@ -92,7 +91,6 @@ words:
- daria
- dcmake
- dearmor
- decryptor
- deleteme
- demultiplexer
- deserializaton
@@ -102,7 +100,6 @@ words:
- distro
- doxyfile
- dxrpl
- elgamal
- enabled
- endmacro
- exceptioned
@@ -113,7 +110,6 @@ words:
- fmtdur
- fsanitize
- funclets
- Gamal
- gcov
- gcovr
- ghead
@@ -203,7 +199,6 @@ words:
- partitioner
- paychan
- paychans
- Pedersen
- permdex
- perminute
- permissioned
@@ -240,7 +235,6 @@ words:
- sahyadri
- Satoshi
- scons
- Schnorr
- secp
- sendq
- seqit
@@ -268,7 +262,6 @@ words:
- stvar
- stvector
- stxchainattestations
- summands
- superpeer
- superpeers
- takergets

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];
}
@@ -296,7 +302,7 @@ set(T& target, std::string const& name, Section const& section)
if ((found_and_valid = val.has_value()))
target = *val;
}
catch (boost::bad_lexical_cast&)
catch (boost::bad_lexical_cast const&) // NOLINT(bugprone-empty-catch)
{
}
return found_and_valid;
@@ -330,7 +336,7 @@ get(Section const& section, std::string const& name, T const& defaultValue = T{}
{
return section.value_or<T>(name, defaultValue);
}
catch (boost::bad_lexical_cast&)
catch (boost::bad_lexical_cast const&) // NOLINT(bugprone-empty-catch)
{
}
return defaultValue;
@@ -345,7 +351,7 @@ get(Section const& section, std::string const& name, char const* defaultValue)
if (val.has_value())
return *val;
}
catch (boost::bad_lexical_cast&)
catch (boost::bad_lexical_cast const&) // NOLINT(bugprone-empty-catch)
{
}
return defaultValue;

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

@@ -112,7 +112,6 @@ private:
return c;
}
public:
CountedObject() noexcept
{
getCounter().increment();
@@ -126,10 +125,13 @@ public:
CountedObject&
operator=(CountedObject const&) noexcept = default;
public:
~CountedObject() noexcept
{
getCounter().decrement();
}
friend Object;
};
} // namespace xrpl

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

@@ -226,7 +226,7 @@ private:
// expensive argument lists if the stream is not active.
#ifndef JLOG
#define JLOG(x) \
if (!x) \
if (!(x)) \
{ \
} \
else \
@@ -235,7 +235,7 @@ private:
#ifndef CLOG
#define CLOG(ss) \
if (!ss) \
if (!(ss)) \
; \
else \
*ss

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

@@ -60,7 +60,7 @@ class SlabAllocator
{
// Use memcpy to avoid unaligned UB
// (will optimize to equivalent code)
std::memcpy(data, &l_, sizeof(std::uint8_t*));
std::memcpy(data, static_cast<void const*>(&l_), sizeof(std::uint8_t*));
l_ = data;
data += item;
}
@@ -98,11 +98,11 @@ class SlabAllocator
ret = l_;
if (ret)
if (ret != nullptr)
{
// Use memcpy to avoid unaligned UB
// (will optimize to equivalent code)
std::memcpy(&l_, ret, sizeof(std::uint8_t*));
std::memcpy(static_cast<void*>(&l_), ret, sizeof(std::uint8_t*));
}
}
@@ -127,7 +127,7 @@ class SlabAllocator
// Use memcpy to avoid unaligned UB
// (will optimize to equivalent code)
std::memcpy(ptr, &l_, sizeof(std::uint8_t*));
std::memcpy(ptr, static_cast<void const*>(&l_), sizeof(std::uint8_t*));
l_ = ptr;
}
};
@@ -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

@@ -26,7 +26,7 @@ struct aged_associative_container_extract_t<false>
Value const&
operator()(Value const& value) const
{
return value;
return value; // NOLINT(bugprone-return-const-ref-from-parameter)
}
};

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

@@ -257,7 +257,8 @@ private:
config_t(config_t&& other)
: KeyValueCompare(std::move(other.key_compare()))
, beast::detail::empty_base_optimization<ElementAllocator>(std::move(other))
, beast::detail::empty_base_optimization<ElementAllocator>(std::move(
static_cast<beast::detail::empty_base_optimization<ElementAllocator>&>(other)))
, clock(other.clock)
{
}

View File

@@ -35,9 +35,11 @@ struct CopyConst<T const, U>
template <typename T, typename Tag>
class ListNode
{
private:
ListNode() = default;
using value_type = T;
friend T;
friend class List<T, Tag>;
template <typename>

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

@@ -203,7 +203,8 @@ template <class Hasher, class T>
inline std::enable_if_t<is_contiguously_hashable<T, Hasher>::value>
hash_append(Hasher& h, T const& t) noexcept
{
h(std::addressof(t), sizeof(t));
// NOLINTNEXTLINE(bugprone-sizeof-expression)
h(static_cast<void const*>(std::addressof(t)), sizeof(t));
}
template <class Hasher, class T>

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

@@ -53,8 +53,9 @@ is_white(char c)
case '\t':
case '\v':
return true;
default:
return false;
};
return false;
}
template <class FwdIter>
@@ -349,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;
}
@@ -359,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

@@ -118,18 +118,18 @@ private:
//------------------------------------------------------------------------------
template <class _>
template <class Unused>
void
reporter<_>::suite_results::add(case_results const& r)
reporter<Unused>::suite_results::add(case_results const& r)
{
++cases;
total += r.total;
failed += r.failed;
}
template <class _>
template <class Unused>
void
reporter<_>::results::add(suite_results const& r)
reporter<Unused>::results::add(suite_results const& r)
{
++suites;
total += r.total;
@@ -160,13 +160,13 @@ reporter<_>::results::add(suite_results const& r)
//------------------------------------------------------------------------------
template <class _>
reporter<_>::reporter(std::ostream& os) : os_(os)
template <class Unused>
reporter<Unused>::reporter(std::ostream& os) : os_(os)
{
}
template <class _>
reporter<_>::~reporter()
template <class Unused>
reporter<Unused>::~reporter()
{
if (results_.top.size() > 0)
{
@@ -180,9 +180,9 @@ reporter<_>::~reporter()
<< amount{results_.failed, "failure"} << std::endl;
}
template <class _>
template <class Unused>
std::string
reporter<_>::fmtdur(typename clock_type::duration const& d)
reporter<Unused>::fmtdur(typename clock_type::duration const& d)
{
using namespace std::chrono;
auto const ms = duration_cast<milliseconds>(d);
@@ -193,46 +193,46 @@ reporter<_>::fmtdur(typename clock_type::duration const& d)
return ss.str();
}
template <class _>
template <class Unused>
void
reporter<_>::on_suite_begin(suite_info const& info)
reporter<Unused>::on_suite_begin(suite_info const& info)
{
suite_results_ = suite_results{info.full_name()};
}
template <class _>
template <class Unused>
void
reporter<_>::on_suite_end()
reporter<Unused>::on_suite_end()
{
results_.add(suite_results_);
}
template <class _>
template <class Unused>
void
reporter<_>::on_case_begin(std::string const& name)
reporter<Unused>::on_case_begin(std::string const& name)
{
case_results_ = case_results(name);
os_ << suite_results_.name << (case_results_.name.empty() ? "" : (" " + case_results_.name))
<< std::endl;
}
template <class _>
template <class Unused>
void
reporter<_>::on_case_end()
reporter<Unused>::on_case_end()
{
suite_results_.add(case_results_);
}
template <class _>
template <class Unused>
void
reporter<_>::on_pass()
reporter<Unused>::on_pass()
{
++case_results_.total;
}
template <class _>
template <class Unused>
void
reporter<_>::on_fail(std::string const& reason)
reporter<Unused>::on_fail(std::string const& reason)
{
++case_results_.failed;
++case_results_.total;
@@ -240,9 +240,9 @@ reporter<_>::on_fail(std::string const& reason)
<< std::endl;
}
template <class _>
template <class Unused>
void
reporter<_>::on_log(std::string const& s)
reporter<Unused>::on_log(std::string const& s)
{
os_ << s;
}

View File

@@ -145,9 +145,9 @@ public:
void
insert(case_results&& r)
{
cont().emplace_back(std::move(r));
total_ += r.tests.total();
failed_ += r.tests.failed();
cont().emplace_back(std::move(r));
}
void

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

@@ -36,7 +36,7 @@ make_reason(String const& reason, char const* file, int line)
} // namespace detail
class thread;
class Thread;
enum abort_t { no_abort_on_fail, abort_on_fail };
@@ -295,7 +295,7 @@ public:
}
private:
friend class thread;
friend class Thread;
static suite**
p_this_suite()
@@ -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());
@@ -538,7 +542,7 @@ suite::run(runner& r)
{
run();
}
catch (abort_exception const&)
catch (abort_exception const&) // NOLINT(bugprone-empty-catch)
{
// ends the suite
}

View File

@@ -14,7 +14,7 @@ namespace beast {
namespace unit_test {
/** Replacement for std::thread that handles exceptions in unit tests. */
class thread
class Thread
{
private:
suite* s_ = nullptr;
@@ -24,17 +24,17 @@ public:
using id = std::thread::id;
using native_handle_type = std::thread::native_handle_type;
thread() = default;
thread(thread const&) = delete;
thread&
operator=(thread const&) = delete;
Thread() = default;
Thread(Thread const&) = delete;
Thread&
operator=(Thread const&) = delete;
thread(thread&& other) : s_(other.s_), t_(std::move(other.t_))
Thread(Thread&& other) : s_(other.s_), t_(std::move(other.t_))
{
}
thread&
operator=(thread&& other)
Thread&
operator=(Thread&& other)
{
s_ = other.s_;
t_ = std::move(other.t_);
@@ -42,10 +42,10 @@ public:
}
template <class F, class... Args>
explicit thread(suite& s, F&& f, Args&&... args) : s_(&s)
explicit Thread(suite& s, F&& f, Args&&... args) : s_(&s)
{
std::function<void(void)> b = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
t_ = std::thread(&thread::run, this, std::move(b));
t_ = std::thread(&Thread::run, this, std::move(b));
}
bool
@@ -80,7 +80,7 @@ public:
}
void
swap(thread& other)
swap(Thread& other)
{
std::swap(s_, other.s_);
std::swap(t_, other.t_);
@@ -94,7 +94,7 @@ private:
{
f();
}
catch (suite::abort_exception const&)
catch (suite::abort_exception const&) // NOLINT(bugprone-empty-catch)
{
}
catch (std::exception const& e)

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

@@ -43,15 +43,15 @@ private:
murmurhash3(result_type x);
};
template <class _>
xor_shift_engine<_>::xor_shift_engine(result_type val)
template <class Unused>
xor_shift_engine<Unused>::xor_shift_engine(result_type val)
{
seed(val);
}
template <class _>
template <class Unused>
void
xor_shift_engine<_>::seed(result_type seed)
xor_shift_engine<Unused>::seed(result_type seed)
{
if (seed == 0)
throw std::domain_error("invalid seed");
@@ -59,9 +59,9 @@ xor_shift_engine<_>::seed(result_type seed)
s_[1] = murmurhash3(s_[0]);
}
template <class _>
template <class Unused>
auto
xor_shift_engine<_>::operator()() -> result_type
xor_shift_engine<Unused>::operator()() -> result_type
{
result_type s1 = s_[0];
result_type const s0 = s_[1];
@@ -70,9 +70,9 @@ xor_shift_engine<_>::operator()() -> result_type
return (s_[1] = (s1 ^ s0 ^ (s1 >> 17) ^ (s0 >> 26))) + s0;
}
template <class _>
template <class Unused>
auto
xor_shift_engine<_>::murmurhash3(result_type x) -> result_type
xor_shift_engine<Unused>::murmurhash3(result_type x) -> result_type
{
x ^= x >> 33;
x *= 0xff51afd7ed558ccdULL;

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

@@ -20,10 +20,6 @@ removeTokenOffersWithLimit(
Keylet const& directory,
std::size_t maxDeletableOffers);
/** Returns tesSUCCESS if NFToken has few enough offers that it can be burned */
TER
notTooManyOffers(ReadView const& view, uint256 const& nftokenID);
/** Finds the specified token in the owner's token directory. */
std::optional<STObject>
findToken(ReadView const& view, AccountID const& owner, uint256 const& nftokenID);

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

@@ -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;
@@ -134,7 +136,7 @@ public:
{
lowest_layer().shutdown(plain_socket::shutdown_both);
}
catch (boost::system::system_error& e)
catch (boost::system::system_error const& e)
{
ec = e.code();
}
@@ -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

@@ -138,9 +138,11 @@ forApiVersions(Fn const& fn, Args&&... args)
{
constexpr auto size = maxVer + 1 - minVer;
[&]<std::size_t... offset>(std::index_sequence<offset...>) {
// NOLINTBEGIN(bugprone-use-after-move)
(((void)fn(
std::integral_constant<unsigned int, minVer + offset>{}, std::forward<Args>(args)...)),
...);
// NOLINTEND(bugprone-use-after-move)
}(std::make_index_sequence<size>{});
}

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

@@ -1,391 +0,0 @@
#pragma once
#include <xrpl/basics/Slice.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/MPTIssue.h>
#include <xrpl/protocol/Protocol.h>
#include <xrpl/protocol/Rate.h>
#include <xrpl/protocol/STLedgerEntry.h>
#include <xrpl/protocol/STObject.h>
#include <xrpl/protocol/Serializer.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/TxFormats.h>
#include <xrpl/protocol/detail/secp256k1.h>
#include <secp256k1_mpt.h>
namespace xrpl {
/**
* @brief Bundles an ElGamal public key with its associated encrypted amount.
*
* Used to represent a recipient in confidential transfers, containing both
* the recipient's ElGamal public key and the ciphertext encrypting the
* transfer amount under that key.
*/
struct ConfidentialRecipient
{
Slice publicKey; ///< The recipient's ElGamal public key (size=xrpl::ecPubKeyLength).
Slice encryptedAmount; ///< The encrypted amount ciphertext
///< (size=xrpl::ecGamalEncryptedTotalLength).
};
/// Holds two secp256k1 public key components representing an ElGamal ciphertext (C1, C2).
struct EcPair
{
secp256k1_pubkey c1;
secp256k1_pubkey c2;
};
/**
* @brief Increments the confidential balance version counter on an MPToken.
*
* The version counter is used to prevent replay attacks by binding proofs
* to a specific state of the account's confidential balance. Wraps to 0
* on overflow (defined behavior for unsigned integers).
*
* @param mptoken The MPToken ledger entry to update.
*/
inline void
incrementConfidentialVersion(STObject& mptoken)
{
// Retrieve current version and increment.
// Unsigned integer overflow is defined behavior in C++ (wraps to 0),
// which is acceptable here.
mptoken[sfConfidentialBalanceVersion] =
mptoken[~sfConfidentialBalanceVersion].value_or(0u) + 1u;
}
/**
* @brief Generates the context hash for ConfidentialMPTSend transactions.
*
* Creates a unique 256-bit hash that binds the zero-knowledge proofs to
* this specific send transaction, preventing proof reuse across transactions.
*
* @param account The sender's account ID.
* @param issuanceID The MPToken Issuance ID.
* @param sequence The transaction sequence number or ticket number.
* @param destination The destination account ID.
* @param version The sender's confidential balance version.
* @return A 256-bit context hash unique to this transaction.
*/
uint256
getSendContextHash(
AccountID const& account,
uint192 const& issuanceID,
std::uint32_t sequence,
AccountID const& destination,
std::uint32_t version);
/**
* @brief Generates the context hash for ConfidentialMPTClawback transactions.
*
* Creates a unique 256-bit hash that binds the equality proof to this
* specific clawback transaction.
*
* @param account The issuer's account ID.
* @param issuanceID The MPToken Issuance ID.
* @param sequence The transaction sequence number or ticket number.
* @param holder The holder's account ID being clawed back from.
* @return A 256-bit context hash unique to this transaction.
*/
uint256
getClawbackContextHash(
AccountID const& account,
uint192 const& issuanceID,
std::uint32_t sequence,
AccountID const& holder);
/**
* @brief Generates the context hash for ConfidentialMPTConvert transactions.
*
* Creates a unique 256-bit hash that binds the Schnorr proof (for key
* registration) to this specific convert transaction.
*
* @param account The holder's account ID.
* @param issuanceID The MPToken Issuance ID.
* @param sequence The transaction sequence number or a ticket number.
* @return A 256-bit context hash unique to this transaction.
*/
uint256
getConvertContextHash(AccountID const& account, uint192 const& issuanceID, std::uint32_t sequence);
/**
* @brief Generates the context hash for ConfidentialMPTConvertBack transactions.
*
* Creates a unique 256-bit hash that binds the zero-knowledge proofs to
* this specific convert-back transaction.
*
* @param account The holder's account ID.
* @param issuanceID The MPToken Issuance ID.
* @param sequence The transaction sequence number or a ticket number.
* @param version The holder's confidential balance version.
* @return A 256-bit context hash unique to this transaction.
*/
uint256
getConvertBackContextHash(
AccountID const& account,
uint192 const& issuanceID,
std::uint32_t sequence,
std::uint32_t version);
/**
* @brief Parses an ElGamal ciphertext into two secp256k1 public key components.
*
* Breaks a 66-byte encrypted amount (two 33-byte compressed EC points) into
* a pair containing (C1, C2) for use in cryptographic operations.
*
* @param buffer The 66-byte buffer containing the compressed ciphertext.
* @return The parsed pair (c1, c2) if successful, std::nullopt if the buffer is invalid.
*/
std::optional<EcPair>
makeEcPair(Slice const& buffer);
/**
* @brief Serializes an EcPair into compressed form.
*
* Converts an EcPair (C1, C2) back into a 66-byte buffer containing
* two 33-byte compressed EC points.
*
* @param pair The EcPair to serialize.
* @return The 66-byte buffer, or std::nullopt if serialization fails.
*/
std::optional<Buffer>
serializeEcPair(EcPair const& pair);
/**
* @brief Verifies that a buffer contains two valid, parsable EC public keys.
*
* @param buffer The input buffer containing two concatenated components.
* @return true if both components can be parsed successfully, false otherwise.
*/
bool
isValidCiphertext(Slice const& buffer);
/**
* @brief Verifies that a buffer contains a valid, parsable compressed EC point.
*
* Can be used to validate both compressed public keys and Pedersen commitments.
* Fails early if the prefix byte is not 0x02 or 0x03.
*
* @param buffer The input buffer containing a compressed EC point (33 bytes).
* @return true if the point can be parsed successfully, false otherwise.
*/
bool
isValidCompressedECPoint(Slice const& buffer);
/**
* @brief Homomorphically adds two ElGamal ciphertexts.
*
* Uses the additive homomorphic property of ElGamal encryption to compute
* Enc(a + b) from Enc(a) and Enc(b) without decryption.
*
* @param a The first ciphertext (66 bytes).
* @param b The second ciphertext (66 bytes).
* @return The resulting ciphertext Enc(a + b), or std::nullopt on failure.
*/
std::optional<Buffer>
homomorphicAdd(Slice const& a, Slice const& b);
/**
* @brief Homomorphically subtracts two ElGamal ciphertexts.
*
* Uses the additive homomorphic property of ElGamal encryption to compute
* Enc(a - b) from Enc(a) and Enc(b) without decryption.
*
* @param a The minuend ciphertext (66 bytes).
* @param b The subtrahend ciphertext (66 bytes).
* @return The resulting ciphertext Enc(a - b), or std::nullopt on failure.
*/
std::optional<Buffer>
homomorphicSubtract(Slice const& a, Slice const& b);
/**
* @brief Encrypts an amount using ElGamal encryption.
*
* Produces a ciphertext C = (C1, C2) where C1 = r*G and C2 = m*G + r*Pk,
* using the provided blinding factor r.
*
* @param amt The plaintext amount to encrypt.
* @param pubKeySlice The recipient's ElGamal public key (size=xrpl::ecPubKeyLength).
* @param blindingFactor The randomness used as blinding factor r
* (size=xrpl::ecBlindingFactorLength).
* @return The ciphertext (size=xrpl::ecGamalEncryptedTotalLength), or std::nullopt on failure.
*/
std::optional<Buffer>
encryptAmount(uint64_t const amt, Slice const& pubKeySlice, Slice const& blindingFactor);
/**
* @brief Generates the canonical zero encryption for a specific MPToken.
*
* Creates a deterministic encryption of zero that is unique to the account
* and MPT issuance. Used to initialize confidential balance fields.
*
* @param pubKeySlice The holder's ElGamal public key (size=xrpl::ecPubKeyLength).
* @param account The account ID of the token holder.
* @param mptId The MPToken Issuance ID.
* @return The canonical zero ciphertext (size=xrpl::ecGamalEncryptedTotalLength), or std::nullopt
* on failure.
*/
std::optional<Buffer>
encryptCanonicalZeroAmount(Slice const& pubKeySlice, AccountID const& account, MPTID const& mptId);
/**
* @brief Verifies a Schnorr proof of knowledge of an ElGamal private key.
*
* Proves that the submitter knows the secret key corresponding to the
* provided public key, without revealing the secret key itself.
*
* @param pubKeySlice The ElGamal public key (size=xrpl::ecPubKeyLength).
* @param proofSlice The Schnorr proof (size=xrpl::ecSchnorrProofLength).
* @param contextHash The 256-bit context hash binding the proof.
* @return tesSUCCESS if valid, or an error code otherwise.
*/
TER
verifySchnorrProof(Slice const& pubKeySlice, Slice const& proofSlice, uint256 const& contextHash);
/**
* @brief Validates the format of encrypted amount fields in a transaction.
*
* Checks that all ciphertext fields in the transaction object have the
* correct length and contain valid EC points. This function is only used
* by ConfidentialMPTConvert and ConfidentialMPTConvertBack transactions.
*
* @param object The transaction object containing encrypted amount fields.
* @return tesSUCCESS if all formats are valid, temMALFORMED if required fields
* are missing, or temBAD_CIPHERTEXT if format validation fails.
*/
NotTEC
checkEncryptedAmountFormat(STObject const& object);
/**
* @brief Verifies revealed amount encryptions for all recipients.
*
* Validates that the same amount was correctly encrypted for the holder,
* issuer, and optionally the auditor using their respective public keys.
*
* @param amount The revealed plaintext amount.
* @param blindingFactor The blinding factor used in all encryptions
* (size=xrpl::ecBlindingFactorLength).
* @param holder The holder's public key and encrypted amount.
* @param issuer The issuer's public key and encrypted amount.
* @param auditor Optional auditor's public key and encrypted amount.
* @return tesSUCCESS if all encryptions are valid, or an error code otherwise.
*/
TER
verifyRevealedAmount(
uint64_t const amount,
Slice const& blindingFactor,
ConfidentialRecipient const& holder,
ConfidentialRecipient const& issuer,
std::optional<ConfidentialRecipient> const& auditor);
/**
* @brief Returns the number of recipients in a confidential transfer.
*
* Returns 4 if an auditor is present (sender, destination, issuer, auditor),
* or 3 if no auditor (sender, destination, issuer).
*
* @param hasAuditor Whether the issuance has an auditor configured.
* @return The number of recipients (3 or 4).
*/
constexpr std::size_t
getConfidentialRecipientCount(bool hasAuditor)
{
return hasAuditor ? 4 : 3;
}
/**
* @brief Verifies a compact sigma clawback proof.
*
* Proves that the issuer knows the exact amount encrypted in the holder's
* balance ciphertext. Used in ConfidentialMPTClawback to verify the issuer
* can decrypt the balance using their private key.
*
* @param amount The revealed plaintext amount.
* @param proof The zero-knowledge proof bytes (ecClawbackProofLength).
* @param pubKeySlice The issuer's ElGamal public key (ecPubKeyLength bytes).
* @param ciphertext The issuer's encrypted balance on the holder's account
* (ecGamalEncryptedTotalLength bytes).
* @param contextHash The 256-bit context hash binding the proof.
* @return tesSUCCESS if the proof is valid, or an error code otherwise.
*/
TER
verifyClawbackProof(
uint64_t const amount,
Slice const& proof,
Slice const& pubKeySlice,
Slice const& ciphertext,
uint256 const& contextHash);
/**
* @brief Generates a cryptographically secure 32-byte blinding factor.
*
* Produces random bytes suitable for use as an ElGamal blinding factor
* or Pedersen commitment randomness.
*
* @return A 32-byte buffer containing the random blinding factor.
*/
Buffer
generateBlindingFactor();
/**
* @brief Verifies all zero-knowledge proofs for a ConfidentialMPTSend transaction.
*
* This function calls mpt_verify_send_proof API in the mpt-crypto utility lib, which verifies the
* equality proof, amount linkage, balance linkage, and range proof.
* Equality proof: Proves the same value is encrypted for the sender, receiver, issuer, and auditor.
* Amount linkage: Proves the send amount matches the amount Pedersen commitment.
* Balance linkage: Proves the sender's balance matches the balance Pedersen
* commitment.
* Range proof: Proves the amount and the remaining balance are within range [0, 2^64-1].
*
* @param proof The full proof blob.
* @param sender The sender's public key and encrypted amount.
* @param destination The destination's public key and encrypted amount.
* @param issuer The issuer's public key and encrypted amount.
* @param auditor The auditor's public key and encrypted amount if present.
* @param spendingBalance The sender's current spending balance ciphertext.
* @param amountCommitment The Pedersen commitment to the send amount.
* @param balanceCommitment The Pedersen commitment to the sender's balance.
* @param contextHash The context hash binding the proof.
* @return tesSUCCESS if all proofs are valid, or an error code otherwise.
*/
TER
verifySendProof(
Slice const& proof,
ConfidentialRecipient const& sender,
ConfidentialRecipient const& destination,
ConfidentialRecipient const& issuer,
std::optional<ConfidentialRecipient> const& auditor,
Slice const& spendingBalance,
Slice const& amountCommitment,
Slice const& balanceCommitment,
uint256 const& contextHash);
/**
* @brief Verifies all zero-knowledge proofs for a ConfidentialMPTConvertBack transaction.
*
* This function calls mpt_verify_convert_back_proof API in the mpt-crypto utility lib, which
* verifies the balance linkage proof and range proof. Balance linkage proof: proves the balance
* commitment matches the spending ciphertext. Range proof: proves the remaining balance after
* convert back is within range [0, 2^64-1].
*
* @param proof The full proof blob.
* @param pubKeySlice The holder's public key.
* @param spendingBalance The holder's spending balance ciphertext.
* @param balanceCommitment The Pedersen commitment to the balance.
* @param amount The amount being converted back to public.
* @param contextHash The context hash binding the proof.
* @return tesSUCCESS if all proofs are valid, or an error code otherwise.
*/
TER
verifyConvertBackProof(
Slice const& proof,
Slice const& pubKeySlice,
Slice const& spendingBalance,
Slice const& balanceCommitment,
uint64_t amount,
uint256 const& contextHash);
} // namespace xrpl

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&
@@ -125,10 +125,12 @@ namespace detail {
#pragma push_macro("XRPL_RETIRE_FIX")
#undef XRPL_RETIRE_FIX
// NOLINTBEGIN(bugprone-macro-parentheses)
#define XRPL_FEATURE(name, supported, vote) +1
#define XRPL_FIX(name, supported, vote) +1
#define XRPL_RETIRE_FEATURE(name) +1
#define XRPL_RETIRE_FIX(name) +1
// NOLINTEND(bugprone-macro-parentheses)
// This value SHOULD be equal to the number of amendments registered in
// Feature.cpp. Because it's only used to reserve storage, and determine how
@@ -373,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

@@ -74,10 +74,12 @@ public:
Derived classes will load the object with all the known formats.
*/
private:
KnownFormats() : name_(beast::type_name<Derived>())
{
}
public:
/** Destroy the known formats object.
The defined formats are deleted.
@@ -181,6 +183,7 @@ private:
boost::container::flat_map<std::string, Item const*> names_;
boost::container::flat_map<KeyType, Item const*> types_;
friend Derived;
};
} // namespace xrpl

View File

@@ -173,8 +173,7 @@ enum LedgerEntryType : std::uint16_t {
LSF_FLAG(lsfMPTCanEscrow, 0x00000008) \
LSF_FLAG(lsfMPTCanTrade, 0x00000010) \
LSF_FLAG(lsfMPTCanTransfer, 0x00000020) \
LSF_FLAG(lsfMPTCanClawback, 0x00000040) \
LSF_FLAG(lsfMPTCanConfidentialAmount, 0x00000080)) \
LSF_FLAG(lsfMPTCanClawback, 0x00000040)) \
\
LEDGER_OBJECT(MPTokenIssuanceMutable, \
LSF_FLAG(lsmfMPTCanMutateCanLock, 0x00000002) \
@@ -184,8 +183,7 @@ enum LedgerEntryType : std::uint16_t {
LSF_FLAG(lsmfMPTCanMutateCanTransfer, 0x00000020) \
LSF_FLAG(lsmfMPTCanMutateCanClawback, 0x00000040) \
LSF_FLAG(lsmfMPTCanMutateMetadata, 0x00010000) \
LSF_FLAG(lsmfMPTCanMutateTransferFee, 0x00020000) \
LSF_FLAG(lsmfMPTCannotMutateCanConfidentialAmount, 0x00040000)) \
LSF_FLAG(lsmfMPTCanMutateTransferFee, 0x00020000)) \
\
LEDGER_OBJECT(MPToken, \
LSF_FLAG2(lsfMPTLocked, 0x00000001) \
@@ -213,7 +211,7 @@ enum LedgerEntryType : std::uint16_t {
// lsfRequireDestTag = 0x00020000,
// ...
// };
#define TO_VALUE(name, value) name = value,
#define TO_VALUE(name, value) name = (value),
#define NULL_NAME(name, values) values
#define NULL_OUTPUT(name, value)
enum LedgerSpecificFlags : std::uint32_t { XMACRO(NULL_NAME, TO_VALUE, NULL_OUTPUT) };

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

@@ -20,7 +20,7 @@ enum GranularPermissionType : std::uint32_t {
#pragma push_macro("PERMISSION")
#undef PERMISSION
#define PERMISSION(type, txType, value) type = value,
#define PERMISSION(type, txType, value) type = (value),
#include <xrpl/protocol/detail/permissions.macro>

View File

@@ -307,51 +307,4 @@ std::size_t constexpr permissionMaxSize = 10;
/** The maximum number of transactions that can be in a batch. */
std::size_t constexpr maxBatchTxCount = 8;
/** Length of one component of EC ElGamal ciphertext */
std::size_t constexpr ecGamalEncryptedLength = 33;
/** EC ElGamal ciphertext length: two 33-byte components concatenated */
std::size_t constexpr ecGamalEncryptedTotalLength = ecGamalEncryptedLength * 2;
/** Length of EC point (compressed) */
std::size_t constexpr compressedECPointLength = 33;
/** Length of EC public key (compressed) */
std::size_t constexpr ecPubKeyLength = compressedECPointLength;
/** Length of EC private key in bytes */
std::size_t constexpr ecPrivKeyLength = 32;
/** Length of the EC blinding factor in bytes */
std::size_t constexpr ecBlindingFactorLength = 32;
/** Length of Schnorr ZKProof for public key registration (compact form) in bytes */
std::size_t constexpr ecSchnorrProofLength = 64;
/** Length of Pedersen Commitment (compressed) */
std::size_t constexpr ecPedersenCommitmentLength = compressedECPointLength;
/** Length of single bulletproof (range proof for 1 commitment) in bytes */
std::size_t constexpr ecSingleBulletproofLength = 688;
/** Length of double bulletproof (range proof for 2 commitments) in bytes */
std::size_t constexpr ecDoubleBulletproofLength = 754;
/** Length of the ZKProof for ConfidentialMPTSend.
* 192 bytes compact sigma proof + 754 bytes double bulletproof. */
std::size_t constexpr ecSendProofLength = 946;
/** Length of the ZKProof for ConfidentialMPTConvertBack.
* 128 bytes compact sigma proof + 688 bytes single bulletproof. */
std::size_t constexpr ecConvertBackProofLength = 816;
/** Length of the ZKProof for ConfidentialMPTClawback. */
std::size_t constexpr ecClawbackProofLength = 64;
/** Compressed EC point prefix for even y-coordinate */
std::uint8_t constexpr ecCompressedPrefixEvenY = 0x02;
/** Compressed EC point prefix for odd y-coordinate */
std::uint8_t constexpr ecCompressedPrefixOddY = 0x03;
} // namespace xrpl

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

@@ -84,7 +84,7 @@ class STCurrency;
#pragma push_macro("TO_MAP")
#undef TO_MAP
#define TO_ENUM(name, value) name = value,
#define TO_ENUM(name, value) name = (value),
#define TO_MAP(name, value) {#name, value},
enum SerializedTypeID { XMACRO(TO_ENUM) };

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