Compare commits

..

15 Commits

Author SHA1 Message Date
Gregory Tsipenyuk
e85f010ef0 Fix AMMClawback return code on AllowTrustLineClawback and NoFreeze check. 2026-04-15 15:49:55 -04:00
Gregory Tsipenyuk
af17ab2642 Merge branch 'develop' into gregtatcam/mpt/assorted-fixes-dev 2026-04-15 14:46:56 -04:00
Gregory Tsipenyuk
70fa0d7f79 Refactor requireAuth handling in ValidMPTTransfer.
* Combine frozen and reqAuth.
* Check senders and receivers for reqAuth.
2026-04-14 09:16:48 -04:00
Gregory Tsipenyuk
a2ab6c79ac Add requireAuth invariant 2026-04-13 15:22:49 -04:00
Gregory Tsipenyuk
5439264bdb Fix MPTInvariant refactoring 2026-04-13 13:39:20 -04:00
Gregory Tsipenyuk
62921eb913 Update src/libxrpl/tx/invariants/MPTInvariant.cpp
Co-authored-by: Shawn Xie <35279399+shawnxie999@users.noreply.github.com>
2026-04-13 13:29:04 -04:00
Gregory Tsipenyuk
50cacddcf8 Add CheckCash can't transfer failure unit-test. 2026-04-10 12:25:01 -04:00
Gregory Tsipenyuk
a839b8b92a Add ValidMPTTransfer invariant unit-tests. 2026-04-10 11:49:43 -04:00
Gregory Tsipenyuk
1a2c0e7d32 Improve ValidMPTTransfer::finalize() 2026-04-10 09:20:56 -04:00
Gregory Tsipenyuk
77df21b485 Address AI review 2026-04-09 17:25:17 -04:00
Gregory Tsipenyuk
63f270f00e Update src/libxrpl/tx/invariants/MPTInvariant.cpp
Co-authored-by: xrplf-ai-reviewer[bot] <266832837+xrplf-ai-reviewer[bot]@users.noreply.github.com>
2026-04-09 14:35:38 -04:00
Gregory Tsipenyuk
0a896b7957 Fix double adjustOwnerCount() in AMMWithdraw. 2026-04-09 13:06:28 -04:00
Gregory Tsipenyuk
12eb050bf8 Change tecFROZEN to tecLOCKED for locked MPT.
Replace checkMPTTxAllowed() with canMPTTradeAndTransfer().
2026-04-09 11:54:15 -04:00
Gregory Tsipenyuk
d26d93130e Replace canTrade with canTransfer in CheckCreate/Cash (Check is not DEX tx). 2026-04-09 11:52:55 -04:00
Gregory Tsipenyuk
a91e8ddad7 Add ValidMPTTransfer invariant. 2026-04-09 11:52:38 -04:00
896 changed files with 2654 additions and 12050 deletions

View File

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

View File

@@ -90,7 +90,6 @@ Checks: "-*,
misc-const-correctness,
misc-definitions-in-headers,
misc-header-include-cycle,
misc-include-cleaner,
misc-misplaced-const,
misc-redundant-expression,
misc-static-assert,
@@ -109,35 +108,37 @@ Checks: "-*,
performance-move-constructor-init,
performance-no-automatic-move,
performance-trivially-destructible,
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-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-duplicate-include,
readability-else-after-return,
readability-enum-initial-value,
readability-implicit-bool-conversion,
readability-make-member-function-const,
readability-math-missing-parentheses,
# 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-misleading-indentation,
readability-non-const-parameter,
readability-redundant-casting,
readability-redundant-declaration,
readability-redundant-inline-specifier,
readability-redundant-member-init,
# readability-redundant-casting, # has issues
# readability-redundant-declaration, # has issues
# readability-redundant-inline-specifier, # has issues
# readability-redundant-member-init, # has issues
readability-redundant-string-init,
readability-reference-to-constructed-temporary,
readability-simplify-boolean-expr,
readability-static-definition-in-anonymous-namespace,
readability-suspicious-call-argument,
# readability-simplify-boolean-expr, # has issues
# readability-static-definition-in-anonymous-namespace, # has issues
# readability-suspicious-call-argument, # has issues
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
@@ -193,7 +194,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)/.*;.*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"
# 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'
#
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.app > xrpld.overlay
xrpld.overlay ~= xrpld.app
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,17 +3,13 @@ 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
@@ -23,22 +19,19 @@ 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
@@ -50,11 +43,12 @@ 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
@@ -62,9 +56,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
@@ -77,17 +71,16 @@ 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
@@ -115,32 +108,27 @@ 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.json
test.overlay > xrpl.ledger
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
@@ -148,7 +136,7 @@ test.peerfinder > xrpl.basics
test.peerfinder > xrpld.core
test.peerfinder > xrpld.peerfinder
test.peerfinder > xrpl.protocol
test.protocol > test.jtx
test.protocol > test.toplevel
test.protocol > test.unit_test
test.protocol > xrpl.basics
test.protocol > xrpl.json
@@ -157,6 +145,7 @@ 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
@@ -170,12 +159,13 @@ 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
@@ -249,20 +239,19 @@ 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
@@ -272,7 +261,6 @@ 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
@@ -284,9 +272,5 @@ 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@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0
with:
path: ${{ env.BUILD_DIR }}/docs/html

View File

@@ -153,32 +153,6 @@ 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:
@@ -192,6 +166,29 @@ 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: |
@@ -203,7 +200,7 @@ jobs:
- name: Upload the binary (Linux)
if: ${{ github.event.repository.visibility == 'public' && runner.os == 'Linux' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
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@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: clang-tidy-results
path: clang-tidy-output.txt

1
.gitignore vendored
View File

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

View File

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

View File

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

View File

@@ -108,12 +108,24 @@ 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,145 +2,308 @@
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 a Python virtual environment for code generation. A venv will be created here by setup_code_gen and used to run generation scripts."
"Path to Python virtual environment for code generation. If provided, automatic venv setup is skipped."
)
# 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")
# 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."
# 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"
)
return()
endif()
# 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"
set(AUTOGEN_TEST_DIR
"${CMAKE_CURRENT_SOURCE_DIR}/src/tests/libxrpl/protocol_autogen"
)
set(SCRIPTS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/scripts")
# 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"
)
# Check if code generation is disabled
if(XRPL_NO_CODEGEN)
message(
WARNING
"Private pip index URL detected: ${PIP_INDEX_URL}\n"
"You may need to connect to VPN to access this URL."
"Protocol autogen: Code generation is disabled (XRPL_NO_CODEGEN=ON). "
"Generated files may be out of date."
)
return()
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
if(WIN32)
set(VENV_PYTHON "${VENV_DIR}/Scripts/python.exe")
set(VENV_PIP "${VENV_DIR}/Scripts/pip.exe")
else()
set(VENV_PYTHON "${VENV_DIR}/bin/python")
set(VENV_PIP "${VENV_DIR}/bin/pip")
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
)
if(NOT TX_LIST_RESULT EQUAL 0)
message(
FATAL_ERROR
"Failed to list transaction output files:\n${TX_LIST_ERROR}"
)
endif()
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}")
# Determine which Python interpreter to use for code generation.
if(CODEGEN_VENV_DIR)
if(WIN32)
set(CODEGEN_PYTHON "${CODEGEN_VENV_DIR}/Scripts/python.exe")
else()
set(CODEGEN_PYTHON "${CODEGEN_VENV_DIR}/bin/python")
# 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()
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"
)
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 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(
setup_code_gen
COMMAND ${Python3_EXECUTABLE} -m venv "${CODEGEN_VENV_DIR}"
COMMAND ${CODEGEN_PYTHON} -m pip install -r "${REQUIREMENTS_FILE}"
# 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}"
COMMENT "Creating venv and installing code generation dependencies..."
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
)
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()
# 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}
)
# 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
add_custom_target(
protocol_autogen_generate
DEPENDS ${TX_OUTPUT_FILES} ${LEDGER_OUTPUT_FILES}
COMMENT "Protocol autogen code generation"
)
# 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()

View File

@@ -1,39 +0,0 @@
#[===================================================================[
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

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

View File

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

View File

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

View File

@@ -67,7 +67,7 @@ private:
}
else
{
while ((elapsed--) != 0u)
while (elapsed--)
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 (true)
while (1)
{
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 (true)
while (1)
{
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 == 0u)
if (!prev.partialDestroyStartedBit)
{
// 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 == 0u)
if (!prev.partialDestroyFinishedBit)
{
// 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 == 0u)
if (!prev.strong)
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 void
static inline void
cleanup(LocalValues* lvs)
{
if ((lvs != nullptr) && !lvs->onCoro)
if (lvs && !lvs->onCoro)
delete lvs;
}
};
@@ -89,7 +89,7 @@ T&
LocalValue<T>::operator*()
{
auto lvs = detail::getLocalValues().get();
if (lvs == nullptr)
if (!lvs)
{
lvs = new detail::LocalValues();
lvs->onCoro = false;

View File

@@ -78,7 +78,7 @@ struct MantissaRange
}
rep min;
rep max{(min * 10) - 1};
rep max{min * 10 - 1};
int log;
mantissa_scale scale;
@@ -342,9 +342,7 @@ public:
constexpr int
signum() const noexcept
{
if (negative_)
return -1;
return (mantissa_ != 0u) ? 1 : 0;
return negative_ ? -1 : (mantissa_ ? 1 : 0);
}
Number
@@ -404,19 +402,19 @@ public:
static void
setMantissaScale(MantissaRange::mantissa_scale scale);
static internalrep
inline static internalrep
minMantissa()
{
return range_.get().min;
}
static internalrep
inline static internalrep
maxMantissa()
{
return range_.get().max;
}
static int
inline static int
mantissaLog()
{
return range_.get().log;
@@ -509,12 +507,16 @@ private:
class Guard;
};
constexpr Number::Number(bool negative, internalrep mantissa, int exponent, unchecked) noexcept
inline constexpr Number::Number(
bool negative,
internalrep mantissa,
int exponent,
unchecked) noexcept
: negative_(negative), mantissa_{mantissa}, exponent_{exponent}
{
}
constexpr Number::Number(internalrep mantissa, int exponent, unchecked) noexcept
inline constexpr Number::Number(internalrep mantissa, int exponent, unchecked) noexcept
: Number(false, mantissa, exponent, unchecked{})
{
}
@@ -546,7 +548,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.
*/
constexpr Number::rep
inline constexpr Number::rep
Number::mantissa() const noexcept
{
auto m = mantissa_;
@@ -567,7 +569,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.
*/
constexpr int
inline constexpr int
Number::exponent() const noexcept
{
auto e = exponent_;
@@ -582,13 +584,13 @@ Number::exponent() const noexcept
return e;
}
constexpr Number
inline constexpr Number
Number::operator+() const noexcept
{
return *this;
}
constexpr Number
inline constexpr Number
Number::operator-() const noexcept
{
if (mantissa_ == 0)
@@ -703,19 +705,17 @@ 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);
}
constexpr Number
inline 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
constexpr Number
inline constexpr Number
squelch(Number const& x, Number const& limit) noexcept
{
if (abs(x) < limit)

View File

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

View File

@@ -98,7 +98,7 @@ class SlabAllocator
ret = l_;
if (ret != nullptr)
if (ret)
{
// Use memcpy to avoid unaligned UB
// (will optimize to equivalent code)
@@ -159,7 +159,7 @@ public:
std::size_t extra,
std::size_t alloc = 0,
std::size_t align = 0)
: itemAlignment_((align != 0u) ? align : alignof(Type))
: itemAlignment_(align ? 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 == nullptr) [[unlikely]]
if (!buf) [[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) == nullptr)
if (!boost::alignment::align(itemAlignment_, itemSize_, slabData, slabSize))
{
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.empty())
if (lhs.size() == 0)
return true;
return std::memcmp(lhs.data(), rhs.data(), lhs.size()) == 0;

View File

@@ -23,10 +23,8 @@ 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,17 +183,11 @@ 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;
@@ -314,10 +308,8 @@ public:
signum() const
{
for (int i = 0; i < WIDTH; i++)
{
if (data_[i] != 0)
return 1;
}
return 0;
}
@@ -398,7 +390,7 @@ public:
return *this;
}
base_uint
base_uint const
operator++(int)
{
// postfix operator
@@ -423,7 +415,7 @@ public:
return *this;
}
base_uint
base_uint const
operator--(int)
{
// postfix operator
@@ -452,7 +444,7 @@ public:
{
std::uint64_t carry = 0;
for (int i = WIDTH - 1; i >= 0; i--)
for (int i = WIDTH; i--;)
{
std::uint64_t const n = carry + boost::endian::big_to_native(data_[i]) +
boost::endian::big_to_native(b.data_[i]);
@@ -540,7 +532,7 @@ using uint256 = base_uint<256>;
using uint192 = base_uint<192>;
template <std::size_t Bits, class Tag>
[[nodiscard]] constexpr std::strong_ordering
[[nodiscard]] inline 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
@@ -561,7 +553,7 @@ operator<=>(base_uint<Bits, Tag> const& lhs, base_uint<Bits, Tag> const& rhs)
}
template <std::size_t Bits, typename Tag>
[[nodiscard]] constexpr bool
[[nodiscard]] inline constexpr bool
operator==(base_uint<Bits, Tag> const& lhs, base_uint<Bits, Tag> const& rhs)
{
return (lhs <=> rhs) == 0;
@@ -569,7 +561,7 @@ operator==(base_uint<Bits, Tag> const& lhs, base_uint<Bits, Tag> const& rhs)
//------------------------------------------------------------------------------
template <std::size_t Bits, class Tag>
constexpr bool
inline constexpr bool
operator==(base_uint<Bits, Tag> const& a, std::uint64_t b)
{
return a == base_uint<Bits, Tag>(b);
@@ -577,28 +569,28 @@ operator==(base_uint<Bits, Tag> const& a, std::uint64_t b)
//------------------------------------------------------------------------------
template <std::size_t Bits, class Tag>
constexpr base_uint<Bits, Tag>
inline 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>
constexpr base_uint<Bits, Tag>
inline 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>
constexpr base_uint<Bits, Tag>
inline 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>
constexpr base_uint<Bits, Tag>
inline 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,8 +231,7 @@ public:
{
// Set partitions to the number of hardware threads if the parameter
// is either empty or set to 0.
partitions_ =
partitions && (*partitions != 0u) ? *partitions : std::thread::hardware_concurrency();
partitions_ = partitions && *partitions ? *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>
constexpr std::enable_if_t<std::is_integral_v<Dest> && std::is_integral_v<Src>, Dest>
inline 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>
constexpr std::enable_if_t<std::is_enum_v<Dest> && std::is_integral_v<Src>, Dest>
inline 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>
constexpr std::enable_if_t<std::is_integral_v<Dest> && std::is_enum_v<Src>, Dest>
inline 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>
constexpr std::enable_if_t<std::is_integral_v<Dest> && std::is_integral_v<Src>, Dest>
inline 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>
constexpr std::enable_if_t<std::is_enum_v<Dest> && std::is_integral_v<Src>, Dest>
inline 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>
constexpr std::enable_if_t<std::is_integral_v<Dest> && std::is_enum_v<Src>, Dest>
inline 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 == nullptr)
if (!m_probe)
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 == nullptr)
if (!m_probe)
return;
typename Clock::time_point const now(Clock::now());
boost::asio::post(

View File

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

View File

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

View File

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

View File

@@ -70,13 +70,9 @@ 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
AddressV4 const
to_v4() const
{
return m_addr.to_v4();
}
AddressV6
AddressV6 const
to_v6() const
{
return m_addr.to_v6();

View File

@@ -350,10 +350,8 @@ 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;
}
@@ -362,10 +360,8 @@ 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--) != 0u)
while (concurrency--)
threads_.emplace_back([&] { ios_.run(); });
}

View File

@@ -32,13 +32,9 @@ 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.empty())
if (m_case.tests.size() > 0)
m_suite.insert(std::move(m_case));
}

View File

@@ -198,10 +198,8 @@ 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;
}
@@ -221,10 +219,8 @@ runner::run_each_if(SequenceContainer const& c, Pred pred)
{
bool failed(false);
for (auto const& s : c)
{
if (pred(s))
failed = run(s) || failed;
}
return failed;
}

View File

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

View File

@@ -13,13 +13,13 @@ enum Severity {
kAll = 0,
kTrace = kAll,
kDebug = 1,
kInfo = 2,
kWarning = 3,
kError = 4,
kFatal = 5,
kDebug,
kInfo,
kWarning,
kError,
kFatal,
kDisabled = 6,
kDisabled,
kNone = kDisabled
};
} // namespace severities
@@ -109,12 +109,12 @@ public:
};
#ifndef __INTELLISENSE__
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>, "");
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, "");
#endif
/** Returns a Sink which does nothing. */
@@ -165,12 +165,12 @@ public:
};
#ifndef __INTELLISENSE__
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>, "");
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, "");
#endif
//--------------------------------------------------------------------------
@@ -247,12 +247,12 @@ public:
};
#ifndef __INTELLISENSE__
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>, "");
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, "");
#endif
//--------------------------------------------------------------------------
@@ -330,12 +330,12 @@ public:
};
#ifndef __INTELLISENSE__
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>, "");
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, "");
#endif
//------------------------------------------------------------------------------

View File

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

View File

@@ -89,7 +89,7 @@ parsePreamble(Slice& s, std::error_code& ec)
p.length = s[0];
s += 1;
if ((p.length & 0x80) != 0u)
if (p.length & 0x80)
{ // 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 = {}; // NOLINT(readability-redundant-member-init)
std::string description{};
auto
toJson() const -> Json::Value;
@@ -68,7 +68,7 @@ public:
contains(PublicKey const& nodeId)
{
std::lock_guard const lock(this->mutex_);
return table_.contains({.nodeId = nodeId, .description = {}});
return table_.find({nodeId}) != table_.end();
}
// Because `ApplicationImp` has two-phase initialization, so must we.

View File

@@ -1,11 +1,12 @@
#pragma once
#include <xrpl/json/json_writer.h>
#include <ostream>
#include <string>
namespace Json {
class Value;
/** Writes a Json::Value to an std::string. */
std::string
to_string(Value const&);
@@ -14,4 +15,8 @@ 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,12 +75,10 @@ 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);
friend bool
inline friend bool
operator>(Key const& lhs, Key const& rhs)
{
return rhs < lhs;
}
friend bool
inline friend bool
operator<=(Key const& lhs, Key const& rhs)
{
return !(lhs > rhs);
}
friend bool
inline friend bool
operator>=(Key const& lhs, Key const& rhs)
{
return !(lhs < rhs);
}
friend bool
inline friend bool
operator==(Key const& lhs, Key const& rhs)
{
return lhs.txId_ == rhs.txId_;
}
friend bool
inline 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_.contains(seq);
return map_.find(seq) != map_.end();
}
/** 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.
auto amounts = getAmounts(*nTakerGets);
if (Quality{amounts} < targetQuality)
if (auto amounts = getAmounts(*nTakerGets); Quality{amounts} < targetQuality)
return getAmounts(detail::reduceOffer(amounts.out));
return amounts;
else
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.
auto amounts = getAmounts(*nTakerPays);
if (Quality{amounts} < targetQuality)
if (auto amounts = getAmounts(*nTakerPays); Quality{amounts} < targetQuality)
return getAmounts(detail::reduceOffer(amounts.in));
return amounts;
else
return amounts;
}
/** Generate AMM offer so that either updated Spot Price Quality (SPQ)
@@ -318,12 +318,9 @@ 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();
auto const res = b * b - 4 * a * c;
if (res < 0)
{
if (auto const res = b * b - 4 * a * c; res < 0)
return std::nullopt; // LCOV_EXCL_LINE
}
if (auto const nTakerPaysPropose = (-b + root2(res)) / (2 * a); nTakerPaysPropose > 0)
else 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
@@ -468,11 +465,13 @@ swapAssetIn(TAmounts<TIn, TOut> const& pool, TIn const& assetIn, std::uint16_t t
return toAmount<TOut>(getAsset(pool.out), swapOut, Number::downward);
}
return toAmount<TOut>(
getAsset(pool.out),
pool.out - (pool.in * pool.out) / (pool.in + assetIn * feeMult(tfee)),
Number::downward);
else
{
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
@@ -534,11 +533,13 @@ swapAssetOut(TAmounts<TIn, TOut> const& pool, TOut const& assetOut, std::uint16_
return toAmount<TIn>(getAsset(pool.in), swapIn, Number::upward);
}
return toAmount<TIn>(
getAsset(pool.in),
((pool.in * pool.out) / (pool.out - assetOut) - pool.in) / feeMult(tfee),
Number::upward);
else
{
return toAmount<TIn>(
getAsset(pool.in),
((pool.in * pool.out) / (pool.out - assetOut) - pool.in) / feeMult(tfee),
Number::upward);
}
}
/** Return square of n.
@@ -622,13 +623,9 @@ 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)
{
forEachItem(view, keylet::ownerDir(id), f);
return forEachItem(view, keylet::ownerDir(id), f);
}
/** Iterate all items after an item in an owner directory.

View File

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

View File

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

View File

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

View File

@@ -44,7 +44,7 @@ public:
}
bool
isSecure() const
isSecure()
{
return mSecure;
}
@@ -126,9 +126,7 @@ public:
async_shutdown(ShutdownHandler handler)
{
if (isSecure())
{
mSocket->async_shutdown(handler);
}
else
{
error_code ec;
@@ -149,13 +147,9 @@ 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>
@@ -163,13 +157,9 @@ 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>
@@ -180,13 +170,9 @@ 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>
@@ -197,13 +183,9 @@ 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>
@@ -211,13 +193,9 @@ 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>
@@ -225,13 +203,9 @@ 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>
@@ -239,13 +213,9 @@ 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>
@@ -253,13 +223,9 @@ 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>
@@ -267,13 +233,9 @@ 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>
@@ -281,13 +243,9 @@ 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,10 +30,8 @@ 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
{
@@ -45,10 +43,8 @@ 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 = 0,
notFound = 1,
dataCorrupt = 2,
unknown = 3,
backendError = 4,
ok,
notFound,
dataCorrupt,
unknown,
backendError,
customCode = 100
};

View File

@@ -113,11 +113,9 @@ 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
@@ -138,12 +136,10 @@ 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;
}
@@ -153,20 +149,16 @@ 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);
@@ -222,7 +214,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;
}
@@ -233,7 +225,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);
@@ -245,7 +237,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,10 +42,8 @@ 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,17 +148,11 @@ 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))
@@ -177,17 +171,11 @@ 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(
@@ -216,21 +204,13 @@ 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>;
@@ -243,21 +223,13 @@ constexpr T
get(STAmount const& a)
{
if constexpr (std::is_same_v<IOUAmount, T>)
{
return a.iou();
}
else if constexpr (std::is_same_v<XRPAmount, T>)
{
return a.xrp();
}
else if constexpr (std::is_same_v<MPTAmount, T>)
{
return a.mpt();
}
else if constexpr (std::is_same_v<STAmount, T>)
{
return a;
}
else
{
constexpr bool alwaysFalse = !std::is_same_v<T, T>;

View File

@@ -221,13 +221,9 @@ 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_);
@@ -239,17 +235,11 @@ 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_);
@@ -277,17 +267,11 @@ 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_);
@@ -308,6 +292,9 @@ 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]] constexpr bool
[[nodiscard]] inline 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]] constexpr std::weak_ordering
[[nodiscard]] inline constexpr std::weak_ordering
operator<=>(Book const& lhs, Book const& rhs)
{
if (auto const c{lhs.in <=> rhs.in}; c != 0)

View File

@@ -107,8 +107,8 @@ validFeatureName(auto fn) -> bool
return true;
}
enum class VoteBehavior : int { Obsolete = -1, DefaultNo = 0, DefaultYes = 1 };
enum class AmendmentSupport : int { Retired = -1, Supported = 0, Unsupported = 1 };
enum class VoteBehavior : int { Obsolete = -1, DefaultNo = 0, DefaultYes };
enum class AmendmentSupport : int { Retired = -1, Supported = 0, Unsupported };
/** All amendments libxrpl knows about. */
std::map<std::string, AmendmentSupport> const&
@@ -375,10 +375,8 @@ 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,9 +151,7 @@ operator bool() const noexcept
inline int
IOUAmount::signum() const noexcept
{
if (mantissa_ < 0)
return -1;
return (mantissa_ != 0) ? 1 : 0;
return (mantissa_ < 0) ? -1 : (mantissa_ ? 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]] constexpr bool
[[nodiscard]] inline constexpr bool
operator==(Issue const& lhs, Issue const& rhs)
{
return (lhs.currency == rhs.currency) && (isXRP(lhs.currency) || lhs.account == rhs.account);

View File

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

View File

@@ -109,9 +109,7 @@ operator bool() const noexcept
constexpr int
MPTAmount::signum() const noexcept
{
if (value_ < 0)
return -1;
return (value_ != 0) ? 1 : 0;
return (value_ < 0) ? -1 : (value_ ? 1 : 0);
}
/** Returns the underlying value. Code SHOULD NOT call this
@@ -143,7 +141,7 @@ mulRatio(MPTAmount const& amt, std::uint32_t num, std::uint32_t den, bool roundU
{
using namespace boost::multiprecision;
if (den == 0u)
if (!den)
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);
static bool
native()
bool
native() const
{
return false;
}
static bool
integral()
bool
integral() const
{
return true;
}
@@ -94,9 +94,9 @@ getMPTIssuer(MPTID const& mptid)
}
// Disallow temporary
AccountID const&
inline AccountID const&
getMPTIssuer(MPTID const&&) = delete;
AccountID const&
inline AccountID const&
getMPTIssuer(MPTID&&) = delete;
inline MPTID

View File

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

View File

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

View File

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

View File

@@ -281,7 +281,7 @@ public:
double const minVD = static_cast<double>(minVMantissa);
double const maxVD =
(expDiff != 0) ? maxVMantissa * pow(10, expDiff) : static_cast<double>(maxVMantissa);
expDiff ? 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,7 +1,6 @@
#pragma once
#include <xrpl/json/json_value.h>
#include <xrpl/protocol/ErrorCodes.h>
namespace xrpl {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -285,7 +285,6 @@ BaseWSPeer<Handler, Impl>::on_write(error_code const& ec)
return;
start_timer();
if (!result.first)
{
impl().ws_.async_write_some(
static_cast<bool>(result.first),
result.second,
@@ -293,9 +292,7 @@ BaseWSPeer<Handler, Impl>::on_write(error_code const& ec)
strand_,
std::bind(
&BaseWSPeer::on_write, impl().shared_from_this(), std::placeholders::_1)));
}
else
{
impl().ws_.async_write_some(
static_cast<bool>(result.first),
result.second,
@@ -303,7 +300,6 @@ BaseWSPeer<Handler, Impl>::on_write(error_code const& ec)
strand_,
std::bind(
&BaseWSPeer::on_write_fin, impl().shared_from_this(), std::placeholders::_1)));
}
}
template <class Handler, class Impl>
@@ -323,9 +319,7 @@ BaseWSPeer<Handler, Impl>::on_write_fin(error_code const& ec)
&BaseWSPeer::on_close, impl().shared_from_this(), std::placeholders::_1)));
}
else if (!wq_.empty())
{
on_write({});
}
}
template <class Handler, class Impl>

View File

@@ -93,7 +93,7 @@ private:
port_.protocol.count("wss2") > 0 || port_.protocol.count("peer") > 0};
bool plain_{
port_.protocol.count("http") > 0 || port_.protocol.count("ws") > 0 ||
(port_.protocol.count("ws2") != 0u)};
port_.protocol.count("ws2")};
static constexpr std::chrono::milliseconds INITIAL_ACCEPT_DELAY{50};
static constexpr std::chrono::milliseconds MAX_ACCEPT_DELAY{2000};
std::chrono::milliseconds accept_delay_{INITIAL_ACCEPT_DELAY};
@@ -297,10 +297,8 @@ void
Door<Handler>::close()
{
if (!strand_.running_in_this_thread())
{
return boost::asio::post(
strand_, std::bind(&Door<Handler>::close, this->shared_from_this()));
}
backoff_timer_.cancel();
error_code ec;
acceptor_.close(ec);
@@ -434,7 +432,11 @@ Door<Handler>::should_throttle_for_fds()
auto const& s = *stats;
auto const free = (s.limit > s.used) ? (s.limit - s.used) : 0ull;
double const free_ratio = static_cast<double>(free) / static_cast<double>(s.limit);
return free_ratio < FREE_FD_THRESHOLD;
if (free_ratio < FREE_FD_THRESHOLD)
{
return true;
}
return false;
#endif
}

View File

@@ -155,7 +155,7 @@ ServerImpl<Handler>::ports(std::vector<Port> const& ports)
list_.push_back(sp);
auto ep = sp->get_endpoint();
if (internalPort.port == 0u)
if (!internalPort.port)
internalPort.port = ep.port();
eps.emplace(port.name, std::move(ep));

View File

@@ -223,10 +223,8 @@ io_list::close(Finisher&& f)
f_ = std::forward<Finisher>(f);
lock.unlock();
for (auto const& p : map)
{
if (auto sp = p.second.lock())
sp->close();
}
}
else
{

View File

@@ -94,10 +94,10 @@ private:
public:
/** Number of children each non-leaf node has (the 'radix tree' part of the
* map) */
static constexpr unsigned int branchFactor = SHAMapInnerNode::branchFactor;
static inline constexpr unsigned int branchFactor = SHAMapInnerNode::branchFactor;
/** The depth of the hash map: data is only present in the leaves */
static constexpr unsigned int leafDepth = 64;
static inline constexpr unsigned int leafDepth = 64;
using DeltaItem =
std::pair<boost::intrusive_ptr<SHAMapItem const>, boost::intrusive_ptr<SHAMapItem const>>;
@@ -658,13 +658,9 @@ inline SHAMap::const_iterator&
SHAMap::const_iterator::operator++()
{
if (auto temp = map_->peekNextItem(item_->key(), stack_))
{
item_ = temp->peekItem().get();
}
else
{
item_ = nullptr;
}
return *this;
}

View File

@@ -15,7 +15,7 @@ class SHAMapInnerNode final : public SHAMapTreeNode, public CountedObject<SHAMap
{
public:
/** Each inner node has 16 children (the 'radix tree' part of the map) */
static constexpr unsigned int branchFactor = 16;
static inline constexpr unsigned int branchFactor = 16;
private:
/** Opaque type that contains the `hashes` array (array of type

View File

@@ -27,7 +27,7 @@ struct ApplyResult
inline bool
isTecClaimHardFail(TER ter, ApplyFlags flags)
{
return isTecClaim(ter) && ((flags & tapRETRY) == 0u);
return isTecClaim(ter) && !(flags & tapRETRY);
}
/** Class describing the consequences to the account

View File

@@ -399,7 +399,8 @@ using InvariantChecks = std::tuple<
ValidLoanBroker,
ValidLoan,
ValidVault,
ValidMPTPayment>;
ValidMPTPayment,
ValidMPTTransfer>;
/**
* @brief get a tuple of all invariant checks

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