Compare commits

..

15 Commits

Author SHA1 Message Date
Mayukha Vadari
d9378e5ee7 Merge branch 'develop' into copilot/add-augmented-submit-fields 2026-03-12 14:37:13 -04:00
Mayukha Vadari
f68f50feb8 Merge branch 'develop' into copilot/add-augmented-submit-fields 2026-03-02 17:06:37 -05:00
Mayukha Vadari
05f20ed3d2 Merge branch 'develop' into copilot/add-augmented-submit-fields 2026-02-27 16:41:55 -05:00
Mayukha Vadari
e1ef9c203a Merge branch 'develop' into copilot/add-augmented-submit-fields 2026-02-27 13:49:32 -05:00
Mayukha Vadari
8a1c4853f0 Merge upstream/develop into copilot/add-augmented-submit-fields 2026-02-26 14:33:50 -05:00
Mayukha Vadari
980b152dca Merge branch 'develop' into copilot/add-augmented-submit-fields 2026-02-06 11:43:47 -05:00
Mayukha Vadari
e15e332130 Merge remote-tracking branch 'upstream/develop' into copilot/add-augmented-submit-fields 2026-02-05 13:33:36 -05:00
Mayukha Vadari
f66a60c842 Merge branch 'develop' into copilot/add-augmented-submit-fields 2026-02-04 16:24:53 -05:00
Mayukha Vadari
af5e8ebad1 Merge remote-tracking branch 'origin/develop' into copilot/add-augmented-submit-fields 2026-02-04 16:22:19 -05:00
Mayukha Vadari
7fac09ccc3 fix issues 2026-01-30 12:14:24 -05:00
copilot-swe-agent[bot]
d18a9e2e54 Extract helper function to avoid code duplication and update API-CHANGELOG
Co-authored-by: mvadari <8029314+mvadari@users.noreply.github.com>
2026-01-30 15:55:51 +00:00
copilot-swe-agent[bot]
a7abee3c7b Fix includes in Submit_test.cpp
Co-authored-by: mvadari <8029314+mvadari@users.noreply.github.com>
2026-01-30 15:29:38 +00:00
copilot-swe-agent[bot]
0affb48188 Fix test to properly construct transaction JSON for sign-and-submit
Co-authored-by: mvadari <8029314+mvadari@users.noreply.github.com>
2026-01-30 15:26:10 +00:00
copilot-swe-agent[bot]
c0f1a1f094 Add augmented fields to sign-and-submit mode and create test
Co-authored-by: mvadari <8029314+mvadari@users.noreply.github.com>
2026-01-30 15:24:51 +00:00
copilot-swe-agent[bot]
72bf625bfe Initial plan 2026-01-30 15:20:54 +00:00
286 changed files with 1357 additions and 1817 deletions

View File

@@ -8,7 +8,6 @@ Checks: "-*,
bugprone-chained-comparison,
bugprone-compare-pointer-to-member-virtual-function,
bugprone-copy-constructor-init,
bugprone-crtp-constructor-accessibility,
bugprone-dangling-handle,
bugprone-dynamic-static-initializers,
bugprone-empty-catch,
@@ -60,29 +59,19 @@ Checks: "-*,
bugprone-suspicious-string-compare,
bugprone-suspicious-stringview-data-usage,
bugprone-swapped-arguments,
bugprone-switch-missing-default-case,
bugprone-terminating-continue,
bugprone-throw-keyword-missing,
bugprone-too-small-loop-variable,
# bugprone-unchecked-optional-access, # see https://github.com/XRPLF/rippled/pull/6502
bugprone-undefined-memory-manipulation,
bugprone-undelegated-constructor,
bugprone-unhandled-exception-at-new,
bugprone-unhandled-self-assignment,
bugprone-unique-ptr-array-mismatch,
bugprone-unsafe-functions,
bugprone-use-after-move,
bugprone-unused-raii,
bugprone-unused-return-value,
bugprone-unused-local-non-trivial-variable,
bugprone-virtual-near-miss,
cppcoreguidelines-init-variables,
cppcoreguidelines-misleading-capture-default-by-value,
cppcoreguidelines-no-suspend-with-lock,
cppcoreguidelines-pro-type-member-init,
cppcoreguidelines-pro-type-static-cast-downcast,
cppcoreguidelines-rvalue-reference-param-not-moved,
cppcoreguidelines-use-default-member-init,
cppcoreguidelines-virtual-class-destructor,
hicpp-ignored-remove-result,
misc-definitions-in-headers,
@@ -92,22 +81,36 @@ Checks: "-*,
misc-throw-by-value-catch-by-reference,
misc-unused-alias-decls,
misc-unused-using-decls,
modernize-deprecated-headers,
modernize-make-shared,
modernize-make-unique,
performance-implicit-conversion-in-loop,
performance-move-constructor-init,
performance-trivially-destructible,
readability-duplicate-include,
readability-enum-initial-value,
readability-misleading-indentation,
readability-non-const-parameter,
readability-redundant-declaration,
readability-reference-to-constructed-temporary
readability-reference-to-constructed-temporary,
modernize-deprecated-headers,
modernize-make-shared,
modernize-make-unique,
performance-implicit-conversion-in-loop,
performance-move-constructor-init,
performance-trivially-destructible
"
# ---
# checks that have some issues that need to be resolved:
#
# bugprone-crtp-constructor-accessibility,
# bugprone-move-forwarding-reference,
# bugprone-switch-missing-default-case,
# bugprone-unused-raii,
# bugprone-unused-return-value,
# bugprone-use-after-move,
#
# cppcoreguidelines-misleading-capture-default-by-value,
# cppcoreguidelines-init-variables,
# cppcoreguidelines-pro-type-member-init,
# cppcoreguidelines-pro-type-static-cast-downcast,
# cppcoreguidelines-use-default-member-init,
# cppcoreguidelines-rvalue-reference-param-not-moved,
#
# llvm-namespace-comment,
# misc-const-correctness,
# misc-include-cleaner,
@@ -192,7 +195,7 @@ CheckOptions:
# readability-identifier-naming.PublicMemberSuffix: ""
# readability-identifier-naming.FunctionIgnoredRegexp: ".*tag_invoke.*"
bugprone-unsafe-functions.ReportMoreUnsafeFunctions: true
bugprone-unused-return-value.CheckedReturnTypes: ::std::error_code;::std::error_condition;::std::errc
# bugprone-unused-return-value.CheckedReturnTypes: ::std::error_code;::std::error_condition;::std::errc
# misc-include-cleaner.IgnoreHeaders: '.*/(detail|impl)/.*;.*(expected|unexpected).*;.*ranges_lower_bound\.h;time.h;stdlib.h;__chrono/.*;fmt/chrono.h;boost/uuid/uuid_hash.hpp'
#
# HeaderFilterRegex: '^.*/(src|tests)/.*\.(h|hpp)$'

View File

@@ -134,7 +134,6 @@ test.peerfinder > xrpld.core
test.peerfinder > xrpld.peerfinder
test.peerfinder > xrpl.protocol
test.protocol > test.toplevel
test.protocol > test.unit_test
test.protocol > xrpl.basics
test.protocol > xrpl.json
test.protocol > xrpl.protocol
@@ -172,7 +171,6 @@ test.shamap > xrpl.shamap
test.toplevel > test.csf
test.toplevel > xrpl.json
test.unit_test > xrpl.basics
test.unit_test > xrpl.protocol
tests.libxrpl > xrpl.basics
tests.libxrpl > xrpl.json
tests.libxrpl > xrpl.net

View File

@@ -1,13 +1,10 @@
name: Check PR title
on:
merge_group:
types:
- checks_requested
pull_request:
types: [opened, edited, reopened, synchronize]
branches: [develop]
jobs:
check_title:
uses: XRPLF/actions/.github/workflows/check-pr-title.yml@c6311685db43aa07971c4a6764320fecbc2acdcd
uses: XRPLF/actions/.github/workflows/check-pr-title.yml@943eb8277e8f4b010fde0c826ce4154c36c39509

View File

@@ -1,9 +1,6 @@
name: Run pre-commit hooks
on:
merge_group:
types:
- checks_requested
pull_request:
push:
branches:

View File

@@ -76,7 +76,7 @@ jobs:
name: ${{ inputs.config_name }}
runs-on: ${{ fromJSON(inputs.runs_on) }}
container: ${{ inputs.image != '' && inputs.image || null }}
timeout-minutes: ${{ inputs.sanitizers != '' && 360 || 60 }}
timeout-minutes: 60
env:
# Use a namespace to keep the objects separate for each configuration.
CCACHE_NAMESPACE: ${{ inputs.config_name }}
@@ -204,17 +204,11 @@ jobs:
- name: Set sanitizer options
if: ${{ !inputs.build_only && env.SANITIZERS_ENABLED == 'true' }}
env:
CONFIG_NAME: ${{ inputs.config_name }}
run: |
ASAN_OPTS="include=${GITHUB_WORKSPACE}/sanitizers/suppressions/runtime-asan-options.txt:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/asan.supp"
if [[ "${CONFIG_NAME}" == *gcc* ]]; then
ASAN_OPTS="${ASAN_OPTS}:alloc_dealloc_mismatch=0"
fi
echo "ASAN_OPTIONS=${ASAN_OPTS}" >> ${GITHUB_ENV}
echo "TSAN_OPTIONS=include=${GITHUB_WORKSPACE}/sanitizers/suppressions/runtime-tsan-options.txt:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/tsan.supp" >> ${GITHUB_ENV}
echo "UBSAN_OPTIONS=include=${GITHUB_WORKSPACE}/sanitizers/suppressions/runtime-ubsan-options.txt:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/ubsan.supp" >> ${GITHUB_ENV}
echo "LSAN_OPTIONS=include=${GITHUB_WORKSPACE}/sanitizers/suppressions/runtime-lsan-options.txt:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/lsan.supp" >> ${GITHUB_ENV}
echo "ASAN_OPTIONS=print_stacktrace=1:detect_container_overflow=0:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/asan.supp" >> ${GITHUB_ENV}
echo "TSAN_OPTIONS=second_deadlock_stack=1:halt_on_error=0:suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/tsan.supp" >> ${GITHUB_ENV}
echo "UBSAN_OPTIONS=suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/ubsan.supp" >> ${GITHUB_ENV}
echo "LSAN_OPTIONS=suppressions=${GITHUB_WORKSPACE}/sanitizers/suppressions/lsan.supp" >> ${GITHUB_ENV}
- name: Run the separate tests
if: ${{ !inputs.build_only }}

View File

@@ -35,10 +35,6 @@ This section contains changes targeting a future version.
- `LEDGER_ENTRY_FLAGS`: Maps ledger entry type names to their flags and flag values.
- `ACCOUNT_SET_FLAGS`: Maps AccountSet flag names (asf flags) to their numeric values.
### Bugfixes
- Peer Crawler: The `port` field in `overlay.active[]` now consistently returns an integer instead of a string for outbound peers. [#6318](https://github.com/XRPLF/rippled/pull/6318)
## XRP Ledger server version 3.1.0
[Version 3.1.0](https://github.com/XRPLF/rippled/releases/tag/3.1.0) was released on Jan 27, 2026.
@@ -88,6 +84,12 @@ This release contains bug fixes only and no API changes.
This release contains bug fixes only and no API changes.
## Unreleased Changes
### Additions and bugfixes
- `submit`: Augmented response fields (`accepted`, `applied`, `broadcast`, `queued`, `kept`, `account_sequence_next`, `account_sequence_available`, `open_ledger_cost`, `validated_ledger_index`) are now included in sign-and-submit mode. Previously, these fields were only returned when submitting a binary transaction blob. ([#6304](https://github.com/XRPLF/rippled/pull/6304))
## XRP Ledger server version 2.5.0
[Version 2.5.0](https://github.com/XRPLF/rippled/releases/tag/2.5.0) was released on Jun 24, 2025.

View File

@@ -118,7 +118,7 @@ if(MSVC)
NOMINMAX
# TODO: Resolve these warnings, don't just silence them
_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:Debug>,$<NOT:$<BOOL:${is_ci}>>>:_CRTDBG_MAP_ALLOC>
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:Debug>>:_CRTDBG_MAP_ALLOC>
)
target_link_libraries(common INTERFACE -errorreport:none -machine:X64)
else()

View File

@@ -23,7 +23,7 @@ target_compile_definitions(
BOOST_FILESYSTEM_NO_DEPRECATED
>
$<$<NOT:$<BOOL:${boost_show_deprecated}>>:
BOOST_COROUTINES2_NO_DEPRECATION_WARNING
BOOST_COROUTINES_NO_DEPRECATION_WARNING
BOOST_BEAST_ALLOW_DEPRECATED
BOOST_FILESYSTEM_DEPRECATED
>

View File

@@ -7,7 +7,7 @@ find_package(
COMPONENTS
chrono
container
context
coroutine
date_time
filesystem
json
@@ -26,7 +26,7 @@ target_link_libraries(
Boost::headers
Boost::chrono
Boost::container
Boost::context
Boost::coroutine
Boost::date_time
Boost::filesystem
Boost::json
@@ -38,26 +38,23 @@ target_link_libraries(
if(Boost_COMPILER)
target_link_libraries(xrpl_boost INTERFACE Boost::disable_autolinking)
endif()
# GCC 14+ has a false positive -Wuninitialized warning in Boost.Coroutine2's
# state.hpp when compiled with -O3. This is due to GCC's intentional behavior
# change (Bug #98871, #119388) where warnings from inlined system header code
# are no longer suppressed by -isystem. The warning occurs in operator|= in
# boost/coroutine2/detail/state.hpp when inlined from push_control_block::destroy().
# See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119388
if(is_gcc AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 14)
target_compile_options(xrpl_boost INTERFACE -Wno-uninitialized)
endif()
# Boost.Context's ucontext backend has ASAN fiber-switching annotations
# (start/finish_switch_fiber) that are compiled in when BOOST_USE_ASAN is defined.
# This tells ASAN about coroutine stack switches, preventing false positive
# stack-use-after-scope errors. BOOST_USE_UCONTEXT ensures the ucontext backend
# is selected (fcontext does not support ASAN annotations).
# These defines must match what Boost was compiled with (see conan/profiles/sanitizers).
if(enable_asan)
target_compile_definitions(
xrpl_boost
INTERFACE BOOST_USE_ASAN BOOST_USE_UCONTEXT
if(SANITIZERS_ENABLED AND is_clang)
# TODO: gcc does not support -fsanitize-blacklist...can we do something else for gcc ?
if(NOT Boost_INCLUDE_DIRS AND TARGET Boost::headers)
get_target_property(
Boost_INCLUDE_DIRS
Boost::headers
INTERFACE_INCLUDE_DIRECTORIES
)
endif()
message(STATUS "Adding [${Boost_INCLUDE_DIRS}] to sanitizer blacklist")
file(
WRITE ${CMAKE_CURRENT_BINARY_DIR}/san_bl.txt
"src:${Boost_INCLUDE_DIRS}/*"
)
target_compile_options(
opts
INTERFACE # ignore boost headers for sanitizing
-fsanitize-blacklist=${CMAKE_CURRENT_BINARY_DIR}/san_bl.txt
)
endif()

View File

@@ -7,21 +7,16 @@ include(default)
{% if compiler == "gcc" %}
{% if "address" in sanitizers or "thread" in sanitizers or "undefinedbehavior" in sanitizers %}
{% set sanitizer_list = [] %}
{% set defines = [] %}
{% set model_code = "" %}
{% set extra_cxxflags = ["-fno-omit-frame-pointer", "-O1", "-Wno-stringop-overflow"] %}
{% if "address" in sanitizers %}
{% set _ = sanitizer_list.append("address") %}
{% set model_code = "-mcmodel=large" %}
{% set _ = defines.append("BOOST_USE_ASAN")%}
{% set _ = defines.append("BOOST_USE_UCONTEXT")%}
{% elif "thread" in sanitizers %}
{% set _ = sanitizer_list.append("thread") %}
{% set model_code = "-mcmodel=medium" %}
{% set _ = extra_cxxflags.append("-Wno-tsan") %}
{% set _ = defines.append("BOOST_USE_TSAN")%}
{% set _ = defines.append("BOOST_USE_UCONTEXT")%}
{% endif %}
{% if "undefinedbehavior" in sanitizers %}
@@ -34,22 +29,16 @@ include(default)
tools.build:cxxflags+=['{{sanitizer_flags}} {{" ".join(extra_cxxflags)}}']
tools.build:sharedlinkflags+=['{{sanitizer_flags}}']
tools.build:exelinkflags+=['{{sanitizer_flags}}']
tools.build:defines+={{defines}}
{% endif %}
{% elif compiler == "apple-clang" or compiler == "clang" %}
{% if "address" in sanitizers or "thread" in sanitizers or "undefinedbehavior" in sanitizers %}
{% set sanitizer_list = [] %}
{% set defines = [] %}
{% set extra_cxxflags = ["-fno-omit-frame-pointer", "-O1"] %}
{% if "address" in sanitizers %}
{% set _ = sanitizer_list.append("address") %}
{% set _ = defines.append("BOOST_USE_ASAN")%}
{% set _ = defines.append("BOOST_USE_UCONTEXT")%}
{% elif "thread" in sanitizers %}
{% set _ = sanitizer_list.append("thread") %}
{% set _ = defines.append("BOOST_USE_TSAN")%}
{% set _ = defines.append("BOOST_USE_UCONTEXT")%}
{% endif %}
{% if "undefinedbehavior" in sanitizers %}
@@ -63,24 +52,8 @@ include(default)
tools.build:cxxflags+=['{{sanitizer_flags}} {{" ".join(extra_cxxflags)}}']
tools.build:sharedlinkflags+=['{{sanitizer_flags}}']
tools.build:exelinkflags+=['{{sanitizer_flags}}']
tools.build:defines+={{defines}}
{% endif %}
{% endif %}
{% endif %}
tools.info.package_id:confs+=["tools.build:cxxflags", "tools.build:exelinkflags", "tools.build:sharedlinkflags", "tools.build:defines"]
[options]
{% if sanitizers %}
{% if "address" in sanitizers %}
# Build Boost.Context with ucontext backend (not fcontext) so that
# ASAN fiber-switching annotations (__sanitizer_start/finish_switch_fiber)
# are compiled into the library. fcontext (assembly) has no ASAN support.
# define=BOOST_USE_ASAN=1 is critical: it must be defined when building
# Boost.Context itself so the ucontext backend compiles in the ASAN annotations.
boost/*:extra_b2_flags=context-impl=ucontext address-sanitizer=on define=BOOST_USE_ASAN=1
boost/*:without_context=False
# Boost stacktrace fails to build with some sanitizers
boost/*:without_stacktrace=True
{% endif %}
{% endif %}
tools.info.package_id:confs+=["tools.build:cxxflags", "tools.build:exelinkflags", "tools.build:sharedlinkflags"]

View File

@@ -1,5 +1,4 @@
import re
import os
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
@@ -58,9 +57,6 @@ class Xrpl(ConanFile):
"tests": False,
"unity": False,
"xrpld": False,
"boost/*:without_context": False,
"boost/*:without_coroutine": True,
"boost/*:without_coroutine2": False,
"date/*:header_only": True,
"ed25519/*:shared": False,
"grpc/*:shared": False,
@@ -130,12 +126,6 @@ class Xrpl(ConanFile):
if self.settings.compiler in ["clang", "gcc"]:
self.options["boost"].without_cobalt = True
# Check if environment variable exists
if "SANITIZERS" in os.environ:
sanitizers = os.environ["SANITIZERS"]
if "address" in sanitizers.lower():
self.default_options["fPIC"] = False
def requirements(self):
# Conan 2 requires transitive headers to be specified
transitive_headers_opt = (
@@ -206,7 +196,7 @@ class Xrpl(ConanFile):
"boost::headers",
"boost::chrono",
"boost::container",
"boost::context",
"boost::coroutine",
"boost::date_time",
"boost::filesystem",
"boost::json",

View File

@@ -99,7 +99,6 @@ words:
- endmacro
- exceptioned
- Falco
- fcontext
- finalizers
- firewalled
- fmtdur
@@ -112,7 +111,6 @@ words:
- gpgcheck
- gpgkey
- hotwallet
- hwaddress
- hwrap
- ifndef
- inequation

View File

@@ -89,8 +89,8 @@ cmake --build . --parallel 4
**IMPORTANT**: ASAN with Boost produces many false positives. Use these options:
```bash
export ASAN_OPTIONS="include=sanitizers/suppressions/runtime-asan-options.txt:suppressions=sanitizers/suppressions/asan.supp"
export LSAN_OPTIONS="include=sanitizers/suppressions/runtime-lsan-options.txt:suppressions=sanitizers/suppressions/lsan.supp"
export ASAN_OPTIONS="print_stacktrace=1:detect_container_overflow=0:suppressions=path/to/asan.supp:halt_on_error=0:log_path=asan.log"
export LSAN_OPTIONS="suppressions=path/to/lsan.supp:halt_on_error=0:log_path=lsan.log"
# Run tests
./xrpld --unittest --unittest-jobs=5
@@ -108,7 +108,7 @@ export LSAN_OPTIONS="include=sanitizers/suppressions/runtime-lsan-options.txt:su
### ThreadSanitizer (TSan)
```bash
export TSAN_OPTIONS="include=sanitizers/suppressions/runtime-tsan-options.txt:suppressions=sanitizers/suppressions/tsan.supp"
export TSAN_OPTIONS="suppressions=path/to/tsan.supp halt_on_error=0 log_path=tsan.log"
# Run tests
./xrpld --unittest --unittest-jobs=5
@@ -129,7 +129,7 @@ More details [here](https://github.com/google/sanitizers/wiki/AddressSanitizerLe
### UndefinedBehaviorSanitizer (UBSan)
```bash
export UBSAN_OPTIONS="include=sanitizers/suppressions/runtime-ubsan-options.txt:suppressions=sanitizers/suppressions/ubsan.supp"
export UBSAN_OPTIONS="suppressions=path/to/ubsan.supp:print_stacktrace=1:halt_on_error=0:log_path=ubsan.log"
# Run tests
./xrpld --unittest --unittest-jobs=5

View File

@@ -1,6 +1,5 @@
#pragma once
#include <xrpl/basics/sanitizers.h>
#include <xrpl/beast/type_name.h>
#include <exception>
@@ -24,28 +23,16 @@ LogThrow(std::string const& title);
When called from within a catch block, it will pass
control to the next matching exception handler, if any.
Otherwise, std::terminate will be called.
ASAN can't handle sudden jumps in control flow very well. This
function is marked as XRPL_NO_SANITIZE_ADDRESS to prevent it from
triggering false positives, since it throws.
*/
[[noreturn]] XRPL_NO_SANITIZE_ADDRESS inline void
[[noreturn]] inline void
Rethrow()
{
LogThrow("Re-throwing exception");
throw;
}
/*
Logs and throws an exception of type E.
ASAN can't handle sudden jumps in control flow very well. This
function is marked as XRPL_NO_SANITIZE_ADDRESS to prevent it from
triggering false positives, since it throws.
*/
template <class E, class... Args>
[[noreturn]] XRPL_NO_SANITIZE_ADDRESS inline void
[[noreturn]] inline void
Throw(Args&&... args)
{
static_assert(

View File

@@ -1,7 +1,5 @@
#pragma once
#include <xrpl/beast/utility/instrumentation.h>
#include <type_traits>
namespace xrpl {
@@ -72,31 +70,4 @@ unsafe_cast(Src s) noexcept
return unsafe_cast<Dest>(static_cast<std::underlying_type_t<Src>>(s));
}
template <class Dest, class Src>
requires std::is_pointer_v<Dest>
inline Dest
safe_downcast(Src* s) noexcept
{
#ifdef NDEBUG
return static_cast<Dest>(s); // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast)
#else
auto* result = dynamic_cast<Dest>(s);
XRPL_ASSERT(result != nullptr, "xrpl::safe_downcast : pointer downcast is valid");
return result;
#endif
}
template <class Dest, class Src>
requires std::is_lvalue_reference_v<Dest>
inline Dest
safe_downcast(Src& s) noexcept
{
#ifndef NDEBUG
XRPL_ASSERT(
dynamic_cast<std::add_pointer_t<std::remove_reference_t<Dest>>>(&s) != nullptr,
"xrpl::safe_downcast : reference downcast is valid");
#endif
return static_cast<Dest>(s); // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast)
}
} // namespace xrpl

View File

@@ -1,13 +0,0 @@
#pragma once
// Helper to disable ASan/HwASan for specific functions
/*
ASAN flags some false positives with sudden jumps in control flow, like
exceptions, or when encountering coroutine stack switches. This macro can be used to disable ASAN
intrumentation for specific functions.
*/
#if defined(__GNUC__) || defined(__clang__)
#define XRPL_NO_SANITIZE_ADDRESS __attribute__((no_sanitize("address", "hwaddress")))
#else
#define XRPL_NO_SANITIZE_ADDRESS
#endif

View File

@@ -43,8 +43,8 @@ private:
template <typename>
friend class ListIterator;
ListNode* m_next = nullptr;
ListNode* m_prev = nullptr;
ListNode* m_next;
ListNode* m_prev;
};
//------------------------------------------------------------------------------
@@ -567,7 +567,7 @@ private:
}
private:
size_type m_size = 0u;
size_type m_size;
Node m_head;
Node m_tail;
};

View File

@@ -1,5 +1,7 @@
#pragma once
#include <xrpl/basics/ByteUtilities.h>
namespace xrpl {
template <class F>
@@ -9,18 +11,16 @@ JobQueue::Coro::Coro(Coro_create_t, JobQueue& jq, JobType type, std::string cons
, name_(name)
, running_(false)
, coro_(
// Stack size of 1MB wasn't sufficient for deep calls. ASAN tests flagged the issue. Hence
// increasing the size to 1.5MB.
boost::context::protected_fixedsize_stack(1536 * 1024),
[this, fn = std::forward<F>(f)](
boost::coroutines2::asymmetric_coroutine<void>::push_type& do_yield) {
boost::coroutines::asymmetric_coroutine<void>::push_type& do_yield) {
yield_ = &do_yield;
yield();
fn(shared_from_this());
#ifndef NDEBUG
finished_ = true;
#endif
})
},
boost::coroutines::attributes(megabytes(1)))
{
}

View File

@@ -7,8 +7,7 @@
#include <xrpl/core/detail/Workers.h>
#include <xrpl/json/json_value.h>
#include <boost/context/protected_fixedsize_stack.hpp>
#include <boost/coroutine2/all.hpp>
#include <boost/coroutine/all.hpp>
#include <set>
@@ -49,8 +48,8 @@ public:
std::mutex mutex_;
std::mutex mutex_run_;
std::condition_variable cv_;
boost::coroutines2::coroutine<void>::pull_type coro_;
boost::coroutines2::coroutine<void>::push_type* yield_;
boost::coroutines::asymmetric_coroutine<void>::pull_type coro_;
boost::coroutines::asymmetric_coroutine<void>::push_type* yield_;
#ifndef NDEBUG
bool finished_ = false;
#endif

View File

@@ -421,7 +421,7 @@ private:
ObjectValues* map_{nullptr};
} value_;
ValueType type_ : 8;
int allocated_ : 1 {}; // Notes: if declared as bool, bitfield is useless.
int allocated_ : 1; // Notes: if declared as bool, bitfield is useless.
};
inline Value

View File

@@ -108,7 +108,7 @@ private:
std::string indentString_;
int rightMargin_;
int indentSize_;
bool addChildValues_{};
bool addChildValues_;
};
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
@@ -175,7 +175,7 @@ private:
std::string indentString_;
int rightMargin_;
std::string indentation_;
bool addChildValues_{};
bool addChildValues_;
};
std::string

View File

@@ -49,7 +49,7 @@ validDomain(ReadView const& view, uint256 domainID, AccountID const& subject);
// This function is only called when we about to return tecNO_PERMISSION
// because all the checks for the DepositPreauth authorization failed.
TER
authorizedDepositPreauth(ReadView const& view, STVector256 const& ctx, AccountID const& dst);
authorizedDepositPreauth(ApplyView const& view, STVector256 const& ctx, AccountID const& dst);
// Sort credentials array, return empty set if there are duplicates
std::set<std::pair<AccountID, Slice>>
@@ -74,7 +74,7 @@ verifyDepositPreauth(
ApplyView& view,
AccountID const& src,
AccountID const& dst,
std::shared_ptr<SLE const> const& sleDst,
std::shared_ptr<SLE> const& sleDst,
beast::Journal j);
} // namespace xrpl

View File

@@ -29,18 +29,6 @@ public:
bool sslVerify,
beast::Journal j);
/** Destroys the global SSL context created by initializeSSLContext().
*
* This releases the underlying boost::asio::ssl::context and any
* associated OpenSSL resources. Must not be called while any
* HTTPClient requests are in flight.
*
* @note Currently only called from tests during teardown. In production,
* the SSL context lives for the lifetime of the process.
*/
static void
cleanupSSLContext();
static void
get(bool bSSL,
boost::asio::io_context& io_context,

View File

@@ -64,49 +64,6 @@
namespace xrpl {
// Feature names must not exceed this length (in characters, excluding the null terminator).
static constexpr std::size_t maxFeatureNameSize = 63;
// Reserve this exact feature-name length (in characters/bytes, excluding the null terminator)
// so that a 32-byte uint256 (for example, in WASM or other interop contexts) can be used
// as a compact, fixed-size feature selector without conflicting with human-readable names.
static constexpr std::size_t reservedFeatureNameSize = 32;
// Both validFeatureNameSize and validFeatureName are consteval functions that can be used in
// static_asserts to validate feature names at compile time. They are only used inside
// enforceValidFeatureName in Feature.cpp, but are exposed here for testing. The expected
// parameter `auto fn` is a constexpr lambda which returns a const char*, making it available
// for compile-time evaluation. Read more in https://accu.org/journals/overload/30/172/wu/
consteval auto
validFeatureNameSize(auto fn) -> bool
{
constexpr char const* n = fn();
// Note, std::strlen is not constexpr, we need to implement our own here.
constexpr std::size_t N = [](auto n) {
std::size_t ret = 0;
for (auto ptr = n; *ptr != '\0'; ret++, ++ptr)
;
return ret;
}(n);
return N != reservedFeatureNameSize && //
N <= maxFeatureNameSize;
}
consteval auto
validFeatureName(auto fn) -> bool
{
constexpr char const* n = fn();
// Prevent the use of visually confusable characters and enforce that feature names
// are always valid ASCII. This is needed because C++ allows Unicode identifiers.
// Characters below 0x20 are nonprintable control characters, and characters with the 0x80 bit
// set are non-ASCII (e.g. UTF-8 encoding of Unicode), so both are disallowed.
for (auto ptr = n; *ptr != '\0'; ++ptr)
{
if (*ptr & 0x80 || *ptr < 0x20)
return false;
}
return true;
}
enum class VoteBehavior : int { Obsolete = -1, DefaultNo = 0, DefaultYes };
enum class AmendmentSupport : int { Retired = -1, Supported = 0, Unsupported };

View File

@@ -209,7 +209,7 @@ std::size_t constexpr maxDIDDocumentLength = 256;
std::size_t constexpr maxDIDURILength = 256;
/** The maximum length of an Attestation inside a DID */
std::size_t constexpr maxDIDDataLength = 256;
std::size_t constexpr maxDIDAttestationLength = 256;
/** The maximum length of a domain */
std::size_t constexpr maxDomainLength = 256;

View File

@@ -44,7 +44,7 @@ protected:
// All the constructed public keys are valid, non-empty and contain 33
// bytes of data.
static constexpr std::size_t size_ = 33;
std::uint8_t buf_[size_]{}; // should be large enough
std::uint8_t buf_[size_]; // should be large enough
public:
using const_iterator = std::uint8_t const*;

View File

@@ -24,7 +24,7 @@ public:
STAccount();
STAccount(SField const& n);
STAccount(SField const& n, Buffer const& v);
STAccount(SField const& n, Buffer&& v);
STAccount(SerialIter& sit, SField const& name);
STAccount(SField const& n, AccountID const& v);

View File

@@ -57,7 +57,7 @@ class STObject : public STBase, public CountedObject<STObject>
using list_type = std::vector<detail::STVar>;
list_type v_;
SOTemplate const* mType{};
SOTemplate const* mType;
public:
using iterator = boost::transform_iterator<Transform, STObject::list_type::const_iterator>;

View File

@@ -15,7 +15,7 @@
namespace xrpl {
enum class TxnSql : char {
enum TxnSql : char {
txnSqlNew = 'N',
txnSqlConflict = 'C',
txnSqlHeld = 'H',
@@ -83,9 +83,6 @@ public:
std::uint32_t
getSeqValue() const;
AccountID
getFeePayer() const;
boost::container::flat_set<AccountID>
getMentionedAccounts() const;
@@ -125,7 +122,7 @@ public:
getMetaSQL(
Serializer rawTxn,
std::uint32_t inLedger,
TxnSql status,
char status,
std::string const& escapedMetaData) const;
std::vector<uint256> const&

View File

@@ -16,11 +16,8 @@ namespace xrpl {
/** A secret key. */
class SecretKey
{
public:
static constexpr std::size_t size_ = 32;
private:
std::uint8_t buf_[size_]{};
std::uint8_t buf_[32];
public:
using const_iterator = std::uint8_t const*;
@@ -30,14 +27,9 @@ public:
SecretKey&
operator=(SecretKey const&) = default;
bool
operator==(SecretKey const&) = delete;
bool
operator!=(SecretKey const&) = delete;
~SecretKey();
SecretKey(std::array<std::uint8_t, size_> const& data);
SecretKey(std::array<std::uint8_t, 32> const& data);
SecretKey(Slice const& slice);
std::uint8_t const*
@@ -86,10 +78,16 @@ public:
};
inline bool
operator==(SecretKey const& lhs, SecretKey const& rhs) = delete;
operator==(SecretKey const& lhs, SecretKey const& rhs)
{
return lhs.size() == rhs.size() && std::memcmp(lhs.data(), rhs.data(), rhs.size()) == 0;
}
inline bool
operator!=(SecretKey const& lhs, SecretKey const& rhs) = delete;
operator!=(SecretKey const& lhs, SecretKey const& rhs)
{
return !(lhs == rhs);
}
//------------------------------------------------------------------------------

View File

@@ -13,7 +13,7 @@ namespace xrpl {
class Seed
{
private:
std::array<uint8_t, 16> buf_{};
std::array<uint8_t, 16> buf_;
public:
using const_iterator = std::array<uint8_t, 16>::const_iterator;

View File

@@ -14,7 +14,7 @@ namespace xrpl {
static inline std::string const&
systemName()
{
static std::string const name = "xrpld";
static std::string const name = "ripple";
return name;
}

View File

@@ -44,7 +44,7 @@ private:
// The largest "small object" we can accommodate
static std::size_t constexpr max_size = 72;
std::aligned_storage<max_size>::type d_ = {};
std::aligned_storage<max_size>::type d_;
STBase* p_ = nullptr;
public:

View File

@@ -40,7 +40,7 @@ public:
operator result_type() noexcept;
private:
char ctx_[96]{};
char ctx_[96];
};
/** SHA-512 digest
@@ -63,7 +63,7 @@ public:
operator result_type() noexcept;
private:
char ctx_[216]{};
char ctx_[216];
};
/** SHA-256 digest
@@ -86,7 +86,7 @@ public:
operator result_type() noexcept;
private:
char ctx_[112]{};
char ctx_[112];
};
//------------------------------------------------------------------------------

View File

@@ -112,7 +112,6 @@ JSS(accounts); // in: LedgerEntry, Subscribe,
// handlers/Ledger, Unsubscribe
JSS(accounts_proposed); // in: Subscribe, Unsubscribe
JSS(action);
JSS(active); // out: OverlayImpl
JSS(acquiring); // out: LedgerRequest
JSS(address); // out: PeerImp
JSS(affected); // out: AcceptedLedgerTx
@@ -301,7 +300,6 @@ JSS(id); // websocket.
JSS(ident); // in: AccountCurrencies, AccountInfo,
// OwnerInfo
JSS(ignore_default); // in: AccountLines
JSS(in); // out: OverlayImpl
JSS(inLedger); // out: tx/Transaction
JSS(inbound); // out: PeerImp
JSS(index); // in: LedgerEntry
@@ -466,7 +464,6 @@ JSS(open_ledger_level); // out: TxQ
JSS(optionality); // out: server_definitions
JSS(oracles); // in: get_aggregate_price
JSS(oracle_document_id); // in: get_aggregate_price
JSS(out); // out: OverlayImpl
JSS(owner); // in: LedgerEntry, out: NetworkOPs
JSS(owner_funds); // in/out: Ledger, NetworkOPs, AcceptedLedgerTx
JSS(page_index);

View File

@@ -114,7 +114,8 @@ protected:
beast::Journal const j_;
AccountID const account_;
XRPAmount preFeeBalance_{}; // Balance before fees.
XRPAmount mPriorBalance; // Balance before fees.
XRPAmount mSourceBalance; // Balance after fees.
virtual ~Transactor() = default;
Transactor(Transactor const&) = delete;

View File

@@ -27,33 +27,6 @@ namespace xrpl {
* communicate the interface required of any invariant checker. Any invariant
* check implementation should implement the public methods documented here.
*
* ## Rules for implementing `finalize`
*
* ### Invariants must run regardless of transaction result
*
* An invariant's `finalize` method MUST perform meaningful checks even when
* the transaction has failed (i.e., `!isTesSuccess(tec)`). The following
* pattern is almost certainly wrong and must never be used:
*
* @code
* // WRONG: skipping all checks on failure defeats the purpose of invariants
* if (!isTesSuccess(tec))
* return true;
* @endcode
*
* The entire purpose of invariants is to detect and prevent the impossible.
* A bug or exploit could cause a failed transaction to mutate ledger state in
* unexpected ways. Invariants are the last line of defense against such
* scenarios.
*
* In general: an invariant that expects a domain-specific state change to
* occur (e.g., a new object being created) should only expect that change
* when the transaction succeeded. A failed VaultCreate must not have created
* a Vault. A failed LoanSet must not have created a Loan.
*
* Also be aware that failed transactions, regardless of type, carry no
* Privileges. Any privilege-gated checks must therefore also be applied to
* failed transactions.
*/
class InvariantChecker_PROTOTYPE
{
@@ -75,11 +48,7 @@ public:
/**
* @brief called after all ledger entries have been visited to determine
* the final status of the check.
*
* This method MUST perform meaningful checks even when `tec` indicates a
* failed transaction. See the class-level documentation for the rules
* governing how failed transactions must be handled.
* the final status of the check
*
* @param tx the transaction being applied
* @param tec the current TER result of the transaction

View File

@@ -22,7 +22,7 @@ private:
uint256 m_dir;
uint256 m_index;
std::shared_ptr<SLE> m_entry;
Quality m_quality{};
Quality m_quality;
public:
/** Create the iterator. */

View File

@@ -370,7 +370,7 @@ changeSpotPriceQuality(
if (!amounts)
{
JLOG(j.trace()) << "changeSpotPrice calc failed: " << to_string(pool.in) << " "
<< to_string(pool.out) << " " << quality << " " << tfee;
<< to_string(pool.out) << " " << quality << " " << tfee << std::endl;
return std::nullopt;
}
@@ -639,9 +639,9 @@ getRoundedAsset(Rules const& rules, STAmount const& balance, A const& frac, IsDe
STAmount
getRoundedAsset(
Rules const& rules,
std::function<Number()> const& noRoundCb,
std::function<Number()>&& noRoundCb,
STAmount const& balance,
std::function<Number()> const& productCb,
std::function<Number()>&& productCb,
IsDeposit isDeposit);
/** Round AMM deposit/withdrawal LPToken amount. Deposit/withdrawal formulas
@@ -672,9 +672,9 @@ getRoundedLPTokens(
STAmount
getRoundedLPTokens(
Rules const& rules,
std::function<Number()> const& noRoundCb,
std::function<Number()>&& noRoundCb,
STAmount const& lptAMMBalance,
std::function<Number()> const& productCb,
std::function<Number()>&& productCb,
IsDeposit isDeposit);
/* Next two functions adjust asset in/out amount to factor in the adjusted

View File

@@ -54,7 +54,7 @@ removeToken(
ApplyView& view,
AccountID const& owner,
uint256 const& nftokenID,
std::shared_ptr<SLE> const& page);
std::shared_ptr<SLE>&& page);
/** Deletes the given token offer.

View File

@@ -1,6 +1,24 @@
# The idea is to empty this file gradually by fixing the underlying issues and removing suppressions.
#
# ASAN_OPTIONS="print_stacktrace=1:detect_container_overflow=0:suppressions=sanitizers/suppressions/asan.supp:halt_on_error=0"
#
# The detect_container_overflow=0 option disables false positives from:
# - Boost intrusive containers (slist_iterator.hpp, hashtable.hpp, aged_unordered_container.h)
# - Boost context/coroutine stack switching (Workers.cpp, thread.h)
#
# See: https://github.com/google/sanitizers/wiki/AddressSanitizerContainerOverflow
# Boost
interceptor_name:boost/asio
# Leaks in Doctest tests: xrpl.test.*
interceptor_name:src/libxrpl/net/HTTPClient.cpp
interceptor_name:src/libxrpl/net/RegisterSSLCerts.cpp
interceptor_name:src/tests/libxrpl/net/HTTPClient.cpp
interceptor_name:xrpl/net/AutoSocket.h
interceptor_name:xrpl/net/HTTPClient.h
interceptor_name:xrpl/net/HTTPClientSSLContext.h
interceptor_name:xrpl/net/RegisterSSLCerts.h
# Suppress false positive stack-buffer errors in thread stack allocation
# Related to ASan's __asan_handle_no_return warnings (github.com/google/sanitizers/issues/189)

View File

@@ -1,5 +1,16 @@
# The idea is to empty this file gradually by fixing the underlying issues and removing suppresions.
# Suppress leaks detected by asan in rippled code.
leak:src/libxrpl/net/HTTPClient.cpp
leak:src/libxrpl/net/RegisterSSLCerts.cpp
leak:src/tests/libxrpl/net/HTTPClient.cpp
leak:xrpl/net/AutoSocket.h
leak:xrpl/net/HTTPClient.h
leak:xrpl/net/HTTPClientSSLContext.h
leak:xrpl/net/RegisterSSLCerts.h
leak:ripple::HTTPClient
leak:ripple::HTTPClientImp
# Suppress leaks detected by asan in boost code.
leak:boost::asio
leak:boost/asio

View File

@@ -1,8 +0,0 @@
detect_container_overflow=false
detect_stack_use_after_return=false
debug=true
halt_on_error=false
print_stats=true
print_cmdline=true
use_sigaltstack=0
print_stacktrace=1

View File

@@ -1 +0,0 @@
halt_on_error=false

View File

@@ -1,3 +0,0 @@
halt_on_error=false
verbosity=1
second_deadlock_stack=1

View File

@@ -1 +0,0 @@
halt_on_error=false

View File

@@ -27,11 +27,3 @@ src:core/JobQueue.cpp
src:libxrpl/beast/utility/beast_Journal.cpp
src:test/beast/beast_PropertyStream_test.cpp
src:src/test/app/Invariants_test.cpp
# ASan false positive: stack-use-after-scope in ErrorCodes.h inline functions.
# When Clang inlines the StaticString overloads (e.g. invalid_field_error(StaticString)),
# ASan scope-poisons the temporary std::string before the inlined callee finishes reading
# through the const ref. This corrupts the coroutine stack and crashes the Simulate test.
# See asan.supp comments for full explanation and planned fix.
[address]
src:*ErrorCodes.h

View File

@@ -182,17 +182,6 @@ signed-integer-overflow:src/test/beast/LexicalCast_test.cpp
# External library suppressions
unsigned-integer-overflow:nudb/detail/xxhash.hpp
# Loan_test.cpp intentional underflow in test arithmetic
unsigned-integer-overflow:src/test/app/Loan_test.cpp
undefined:src/test/app/Loan_test.cpp
# Source tree restructured paths (libxrpl/tx/transactors/)
# These duplicate the xrpld/app/tx/detail entries above for the new layout
unsigned-integer-overflow:src/libxrpl/tx/transactors/oracle/SetOracle.cpp
undefined:src/libxrpl/tx/transactors/oracle/SetOracle.cpp
unsigned-integer-overflow:src/libxrpl/tx/transactors/nft/NFTokenMint.cpp
undefined:src/libxrpl/tx/transactors/nft/NFTokenMint.cpp
# Protobuf intentional overflows in hash functions
# Protobuf uses intentional unsigned overflow for hash computation (stringpiece.h:393)
unsigned-integer-overflow:google/protobuf/stubs/stringpiece.h

View File

@@ -51,8 +51,8 @@ extractTarLz4(boost::filesystem::path const& src, boost::filesystem::path const&
if (archive_write_disk_set_standard_lookup(aw.get()) < ARCHIVE_OK)
Throw<std::runtime_error>(archive_error_string(aw.get()));
int result = 0;
struct archive_entry* entry = nullptr;
int result;
struct archive_entry* entry;
while (true)
{
result = archive_read_next_header(ar.get(), &entry);
@@ -67,9 +67,9 @@ extractTarLz4(boost::filesystem::path const& src, boost::filesystem::path const&
if (archive_entry_size(entry) > 0)
{
void const* buf = nullptr;
size_t sz = 0;
la_int64_t offset = 0;
void const* buf;
size_t sz;
la_int64_t offset;
while (true)
{
result = archive_read_data_block(ar.get(), &buf, &sz, &offset);

View File

@@ -66,12 +66,14 @@ concept UnsignedMantissa = std::is_unsigned_v<T> || std::is_same_v<T, uint128_t>
class Number::Guard
{
std::uint64_t digits_{0}; // 16 decimal guard digits
std::uint8_t xbit_ : 1 {0}; // has a non-zero digit been shifted off the end
std::uint8_t sbit_ : 1 {0}; // the sign of the guard digits
std::uint64_t digits_; // 16 decimal guard digits
std::uint8_t xbit_ : 1; // has a non-zero digit been shifted off the end
std::uint8_t sbit_ : 1; // the sign of the guard digits
public:
explicit Guard() = default;
explicit Guard() : digits_{0}, xbit_{0}, sbit_{0}
{
}
// set & test the sign bit
void
@@ -256,7 +258,7 @@ Number::Guard::doRoundUp(
}
bringIntoRange(negative, mantissa, exponent, minMantissa);
if (exponent > maxExponent)
Throw<std::overflow_error>(std::string(location));
throw std::overflow_error(location);
}
template <UnsignedMantissa T>
@@ -296,7 +298,7 @@ Number::Guard::doRound(rep& drops, std::string location)
// or "(maxRep + 1) / 10", neither of which will round up when
// converting to rep, though the latter might overflow _before_
// rounding.
Throw<std::overflow_error>(std::string(location)); // LCOV_EXCL_LINE
throw std::overflow_error(location); // LCOV_EXCL_LINE
}
++drops;
}

View File

@@ -35,6 +35,7 @@ namespace xrpl {
template <class Derived>
class AsyncObject
{
protected:
AsyncObject() : m_pending(0)
{
}
@@ -92,8 +93,6 @@ public:
private:
// The number of handlers pending.
std::atomic<int> m_pending;
friend Derived;
};
class ResolverAsioImpl : public ResolverAsio, public AsyncObject<ResolverAsioImpl>
@@ -109,7 +108,7 @@ public:
std::condition_variable m_cv;
std::mutex m_mut;
bool m_asyncHandlersCompleted{true};
bool m_asyncHandlersCompleted;
std::atomic<bool> m_stop_called;
std::atomic<bool> m_stopped;
@@ -136,6 +135,7 @@ public:
, m_io_context(io_context)
, m_strand(boost::asio::make_strand(io_context))
, m_resolver(io_context)
, m_asyncHandlersCompleted(true)
, m_stop_called(false)
, m_stopped(true)
{

View File

@@ -103,7 +103,7 @@ trim_whitespace(std::string str)
std::optional<std::uint64_t>
to_uint64(std::string const& s)
{
std::uint64_t result = 0;
std::uint64_t result;
if (beast::lexicalCastChecked(result, s))
return result;
return std::nullopt;

View File

@@ -116,7 +116,6 @@ encode(void* dest, void const* src, std::size_t len)
in += 3;
}
// NOLINTNEXTLINE(bugprone-switch-missing-default-case)
switch (len % 3)
{
case 2:

View File

@@ -239,7 +239,6 @@ initAuthenticated(
{
boost::system::error_code ec;
// NOLINTNEXTLINE(bugprone-unused-return-value)
context.use_certificate_file(cert_file, boost::asio::ssl::context::pem, ec);
if (ec)
@@ -299,7 +298,6 @@ initAuthenticated(
{
boost::system::error_code ec;
// NOLINTNEXTLINE(bugprone-unused-return-value)
context.use_private_key_file(key_file, boost::asio::ssl::context::pem, ec);
if (ec)

View File

@@ -16,7 +16,7 @@ class seconds_clock_thread
{
using Clock = basic_seconds_clock::Clock;
bool stop_{false};
bool stop_;
std::mutex mut_;
std::condition_variable cv_;
std::thread thread_;
@@ -48,7 +48,8 @@ seconds_clock_thread::~seconds_clock_thread()
thread_.join();
}
seconds_clock_thread::seconds_clock_thread() : tp_{Clock::now().time_since_epoch().count()}
seconds_clock_thread::seconds_clock_thread()
: stop_{false}, tp_{Clock::now().time_since_epoch().count()}
{
thread_ = std::thread(&seconds_clock_thread::run, this);
}

View File

@@ -29,7 +29,7 @@ print_identifiers(SemanticVersion::identifier_list const& list)
bool
isNumeric(std::string const& s)
{
int n = 0;
int n;
// Must be convertible to an integer
if (!lexicalCastChecked(n, s))
@@ -68,7 +68,7 @@ chopUInt(int& value, int limit, std::string& input)
if (item.empty())
return false;
int n = 0;
int n;
// Must be convertible to an integer
if (!lexicalCastChecked(n, item))

View File

@@ -104,8 +104,8 @@ private:
std::shared_ptr<StatsDCollectorImp> m_impl;
std::string m_name;
CounterImpl::value_type m_value{0};
bool m_dirty{false};
CounterImpl::value_type m_value;
bool m_dirty;
};
//------------------------------------------------------------------------------
@@ -162,9 +162,9 @@ private:
std::shared_ptr<StatsDCollectorImp> m_impl;
std::string m_name;
GaugeImpl::value_type m_last_value{0};
GaugeImpl::value_type m_value{0};
bool m_dirty{false};
GaugeImpl::value_type m_last_value;
GaugeImpl::value_type m_value;
bool m_dirty;
};
//------------------------------------------------------------------------------
@@ -194,8 +194,8 @@ private:
std::shared_ptr<StatsDCollectorImp> m_impl;
std::string m_name;
MeterImpl::value_type m_value{0};
bool m_dirty{false};
MeterImpl::value_type m_value;
bool m_dirty;
};
//------------------------------------------------------------------------------
@@ -470,7 +470,6 @@ public:
m_io_context.run();
// NOLINTNEXTLINE(bugprone-unused-return-value)
m_socket.shutdown(boost::asio::ip::udp::socket::shutdown_send, ec);
m_socket.close();
@@ -505,7 +504,7 @@ StatsDHookImpl::do_process()
StatsDCounterImpl::StatsDCounterImpl(
std::string const& name,
std::shared_ptr<StatsDCollectorImp> const& impl)
: m_impl(impl), m_name(name)
: m_impl(impl), m_name(name), m_value(0), m_dirty(false)
{
m_impl->add(*this);
}
@@ -587,7 +586,7 @@ StatsDEventImpl::do_notify(EventImpl::value_type const& value)
StatsDGaugeImpl::StatsDGaugeImpl(
std::string const& name,
std::shared_ptr<StatsDCollectorImp> const& impl)
: m_impl(impl), m_name(name)
: m_impl(impl), m_name(name), m_last_value(0), m_value(0), m_dirty(false)
{
m_impl->add(*this);
}
@@ -676,7 +675,7 @@ StatsDGaugeImpl::do_process()
StatsDMeterImpl::StatsDMeterImpl(
std::string const& name,
std::shared_ptr<StatsDCollectorImp> const& impl)
: m_impl(impl), m_name(name)
: m_impl(impl), m_name(name), m_value(0), m_dirty(false)
{
m_impl->add(*this);
}

View File

@@ -159,7 +159,7 @@ operator>>(std::istream& is, Endpoint& endpoint)
if (is.rdbuf()->in_avail() > 0)
{
Port port = 0;
Port port;
is >> port;
if (is.fail())
return is;

View File

@@ -15,7 +15,7 @@ namespace beast {
//
//------------------------------------------------------------------------------
PropertyStream::Item::Item(Source* source) : ListNode(), m_source(source)
PropertyStream::Item::Item(Source* source) : m_source(source)
{
}

View File

@@ -331,7 +331,7 @@ JobQueue::finishJob(JobType type)
void
JobQueue::processTask(int instance)
{
JobType type = jtINVALID;
JobType type;
{
using namespace std::chrono;

View File

@@ -1,4 +1,5 @@
#include <xrpl/beast/core/CurrentThreadName.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/core/PerfLog.h>
#include <xrpl/core/detail/Workers.h>
@@ -95,13 +96,11 @@ Workers::stop()
{
setNumberOfThreads(0);
// Wait until all workers have paused AND no tasks are actively running.
// Both conditions are needed because m_allPaused (mutex-protected) and
// m_runningTaskCount (atomic) are not synchronized under the same lock,
// so m_allPaused can momentarily be true while a task is still finishing.
std::unique_lock<std::mutex> lk{m_mut};
m_cv.wait(lk, [this] { return m_allPaused && numberOfCurrentlyRunningTasks() == 0; });
m_cv.wait(lk, [this] { return m_allPaused; });
lk.unlock();
XRPL_ASSERT(numberOfCurrentlyRunningTasks() == 0, "xrpl::Workers::stop : zero running tasks");
}
void
@@ -218,18 +217,7 @@ Workers::Worker::run()
//
++m_workers.m_runningTaskCount;
m_workers.m_callback.processTask(instance_);
// When the running task count drops to zero, wake stop() which
// may be waiting for both m_allPaused and zero running tasks.
// Locking m_mut before notify_all() prevents a lost wakeup:
// it serializes against the predicate check inside stop()'s
// cv.wait(), ensuring the notification is not missed between
// the predicate evaluation and the actual sleep.
if (--m_workers.m_runningTaskCount == 0)
{
std::lock_guard lk{m_workers.m_mut};
m_workers.m_cv.notify_all();
}
--m_workers.m_runningTaskCount;
}
// Any worker that goes into the paused list must

View File

@@ -198,10 +198,10 @@ char const* RFC1751::s_dictionary[2048] = {
unsigned long
RFC1751::extract(char const* s, int start, int length)
{
unsigned char cl = 0;
unsigned char cc = 0;
unsigned char cr = 0;
unsigned long x = 0;
unsigned char cl;
unsigned char cc;
unsigned char cr;
unsigned long x;
XRPL_ASSERT(length <= 11, "xrpl::RFC1751::extract : maximum length");
XRPL_ASSERT(start >= 0, "xrpl::RFC1751::extract : minimum start");
@@ -226,7 +226,7 @@ void
RFC1751::btoe(std::string& strHuman, std::string const& strData)
{
char caBuffer[9]; /* add in room for the parity 2 bits*/
int p = 0, i = 0;
int p, i;
memcpy(caBuffer, strData.c_str(), 8);
@@ -245,11 +245,11 @@ RFC1751::btoe(std::string& strHuman, std::string const& strData)
void
RFC1751::insert(char* s, int x, int start, int length)
{
unsigned char cl = 0;
unsigned char cc = 0;
unsigned char cr = 0;
unsigned long y = 0;
int shift = 0;
unsigned char cl;
unsigned char cc;
unsigned char cr;
unsigned long y;
int shift;
XRPL_ASSERT(length <= 11, "xrpl::RFC1751::insert : maximum length");
XRPL_ASSERT(start >= 0, "xrpl::RFC1751::insert : minimum start");
@@ -336,7 +336,7 @@ RFC1751::etob(std::string& strData, std::vector<std::string> vsHuman)
if (6 != vsHuman.size())
return -1;
int i = 0, p = 0;
int i, p = 0;
char b[9] = {0};
for (auto& strWord : vsHuman)

View File

@@ -30,7 +30,7 @@ csprng_engine::~csprng_engine()
void
csprng_engine::mix_entropy(void* buffer, std::size_t count)
{
std::array<std::random_device::result_type, 128> entropy{};
std::array<std::random_device::result_type, 128> entropy;
{
// On every platform we support, std::random_device
@@ -71,7 +71,7 @@ csprng_engine::operator()(void* ptr, std::size_t count)
csprng_engine::result_type
csprng_engine::operator()()
{
result_type ret = 0;
result_type ret;
(*this)(&ret, sizeof(result_type));
return ret;
}

View File

@@ -196,7 +196,7 @@ private:
explicit Collection() = default;
/** What type of collection are we in? */
Writer::CollectionType type = Writer::CollectionType::array;
Writer::CollectionType type;
/** Is this the first entry in a collection?
* If false, we have to emit a , before we write the next entry. */

View File

@@ -94,7 +94,7 @@ Reader::parse(char const* beginDoc, char const* endDoc, Value& root)
nodes_.push(&root);
bool successful = readValue(0);
Token token{};
Token token;
skipCommentTokens(token);
if (!root.isNull() && !root.isArray() && !root.isObject())
@@ -114,7 +114,7 @@ Reader::parse(char const* beginDoc, char const* endDoc, Value& root)
bool
Reader::readValue(unsigned depth)
{
Token token{};
Token token;
skipCommentTokens(token);
if (depth > nest_limit)
return addError("Syntax error: maximum nesting depth exceeded", token);
@@ -395,7 +395,7 @@ Reader::readString()
bool
Reader::readObject(Token& tokenStart, unsigned depth)
{
Token tokenName{};
Token tokenName;
std::string name;
currentValue() = Value(objectValue);
@@ -420,7 +420,7 @@ Reader::readObject(Token& tokenStart, unsigned depth)
if (!decodeString(tokenName, name))
return recoverFromError(tokenObjectEnd);
Token colon{};
Token colon;
if (!readToken(colon) || colon.type_ != tokenMemberSeparator)
{
@@ -440,7 +440,7 @@ Reader::readObject(Token& tokenStart, unsigned depth)
if (!ok) // error already set
return recoverFromError(tokenObjectEnd);
Token comma{};
Token comma;
if (!readToken(comma) ||
(comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
@@ -470,7 +470,7 @@ Reader::readArray(Token& tokenStart, unsigned depth)
if (*current_ == ']') // empty array
{
Token endArray{};
Token endArray;
readToken(endArray);
return true;
}
@@ -487,7 +487,7 @@ Reader::readArray(Token& tokenStart, unsigned depth)
if (!ok) // error already set
return recoverFromError(tokenArrayEnd);
Token token{};
Token token;
// Accept Comment after last item in the array.
ok = readToken(token);
@@ -591,7 +591,7 @@ Reader::decodeDouble(Token& token)
{
double value = 0;
int const bufferSize = 32;
int count = 0;
int count;
int length = int(token.end_ - token.start_);
// Sanity check to avoid buffer overflow exploits.
if (length < 0)
@@ -689,7 +689,7 @@ Reader::decodeString(Token& token, std::string& decoded)
break;
case 'u': {
unsigned int unicode = 0;
unsigned int unicode;
if (!decodeUnicodeCodePoint(token, current, end, unicode))
return false;
@@ -727,7 +727,7 @@ Reader::decodeUnicodeCodePoint(Token& token, Location& current, Location end, un
token,
current);
unsigned int surrogatePair = 0;
unsigned int surrogatePair;
if (*current != '\\' || *(current + 1) != 'u')
return addError(
@@ -796,7 +796,7 @@ bool
Reader::recoverFromError(TokenType skipUntilToken)
{
int errorCount = int(errors_.size());
Token skip{};
Token skip;
while (true)
{
@@ -867,7 +867,7 @@ Reader::getLocationLineAndColumn(Location location, int& line, int& column) cons
std::string
Reader::getLocationLineAndColumn(Location location) const
{
int line = 0, column = 0;
int line, column;
getLocationLineAndColumn(location, line, column);
return "Line " + std::to_string(line) + ", Column " + std::to_string(column);
}

View File

@@ -157,7 +157,7 @@ Value::CZString::isStaticString() const
* memset( this, 0, sizeof(Value) )
* This optimization is used in ValueInternalMap fast allocator.
*/
Value::Value(ValueType type) : type_(type)
Value::Value(ValueType type) : type_(type), allocated_(0)
{
switch (type)
{
@@ -225,7 +225,7 @@ Value::Value(std::string const& value) : type_(stringValue), allocated_(true)
valueAllocator()->duplicateStringValue(value.c_str(), (unsigned int)value.length());
}
Value::Value(StaticString const& value) : type_(stringValue)
Value::Value(StaticString const& value) : type_(stringValue), allocated_(false)
{
value_.string_ = const_cast<char*>(value.c_str());
}

View File

@@ -107,7 +107,7 @@ ApplyStateTable::apply(
Mods newMod;
for (auto& item : items_)
{
SField const* type = nullptr;
SField const* type;
switch (item.second.first)
{
default:
@@ -513,7 +513,7 @@ void
ApplyStateTable::threadItem(TxMeta& meta, std::shared_ptr<SLE> const& sle)
{
key_type prevTxID;
LedgerIndex prevLgrID = 0;
LedgerIndex prevLgrID;
if (!sle->thread(meta.getTxID(), meta.getLgrSeq(), prevTxID, prevLgrID))
return;

View File

@@ -197,7 +197,7 @@ validDomain(ReadView const& view, uint256 domainID, AccountID const& subject)
}
TER
authorizedDepositPreauth(ReadView const& view, STVector256 const& credIDs, AccountID const& dst)
authorizedDepositPreauth(ApplyView const& view, STVector256 const& credIDs, AccountID const& dst)
{
std::set<std::pair<AccountID, Slice>> sorted;
std::vector<std::shared_ptr<SLE const>> lifeExtender;
@@ -318,7 +318,7 @@ verifyDepositPreauth(
ApplyView& view,
AccountID const& src,
AccountID const& dst,
std::shared_ptr<SLE const> const& sleDst,
std::shared_ptr<SLE> const& sleDst,
beast::Journal j)
{
// If depositPreauth is enabled, then an account that requires

View File

@@ -1321,7 +1321,7 @@ doWithdraw(
}
else
{
auto dstSle = view.read(keylet::account(dstAcct));
auto dstSle = view.peek(keylet::account(dstAcct));
if (auto err = verifyDepositPreauth(tx, view, senderAcct, dstAcct, dstSle, j))
return err;
}

View File

@@ -26,12 +26,6 @@ HTTPClient::initializeSSLContext(
httpClientSSLContext.emplace(sslVerifyDir, sslVerifyFile, sslVerify, j);
}
void
HTTPClient::cleanupSSLContext()
{
httpClientSSLContext.reset();
}
//------------------------------------------------------------------------------
//
// Fetch a web page via http or https.
@@ -478,7 +472,7 @@ public:
private:
using pointer = std::shared_ptr<HTTPClient>;
bool mSSL{};
bool mSSL;
AutoSocket mSocket;
boost::asio::ip::tcp::resolver mResolver;
@@ -496,7 +490,7 @@ private:
std::string mBody;
unsigned short const mPort;
std::size_t const maxResponseSize_;
int mStatus{};
int mStatus;
std::function<void(boost::asio::streambuf& sb, std::string const& strHost)> mBuild;
std::function<
bool(boost::system::error_code const& ecResult, int iStatus, std::string const& strData)>
@@ -508,7 +502,7 @@ private:
boost::system::error_code mShutdown;
std::deque<std::string> mDeqSites;
std::chrono::seconds mTimeout{};
std::chrono::seconds mTimeout;
beast::Journal j_;
};

View File

@@ -79,7 +79,6 @@ registerSSLCerts(boost::asio::ssl::context& ctx, boost::system::error_code& ec,
SSL_CTX_set_cert_store(ctx.native_handle(), store.release());
#else
// NOLINTNEXTLINE(bugprone-unused-return-value)
ctx.set_default_verify_paths(ec);
#endif
}

View File

@@ -75,7 +75,7 @@ BatchWriter::writeBatch()
}
}
BatchWriteReport report{};
BatchWriteReport report;
report.writeCount = set.size();
auto const before = std::chrono::steady_clock::now();

View File

@@ -29,7 +29,7 @@ DatabaseNodeImp::fetchNodeObject(
bool duplicate)
{
std::shared_ptr<NodeObject> nodeObject = nullptr;
Status status = ok;
Status status;
try
{

View File

@@ -101,7 +101,7 @@ DatabaseRotatingImp::fetchNodeObject(
bool duplicate)
{
auto fetch = [&](std::shared_ptr<Backend> const& backend) {
Status status = ok;
Status status;
std::shared_ptr<NodeObject> nodeObject;
try
{

View File

@@ -181,7 +181,7 @@ public:
Status
fetch(uint256 const& hash, std::shared_ptr<NodeObject>* pno) override
{
Status status = ok;
Status status;
pno->reset();
nudb::error_code ec;
db_.fetch(
@@ -239,7 +239,7 @@ public:
void
store(std::shared_ptr<NodeObject> const& no) override
{
BatchWriteReport report{};
BatchWriteReport report;
report.writeCount = 1;
auto const start = std::chrono::steady_clock::now();
do_insert(no);
@@ -251,7 +251,7 @@ public:
void
storeBatch(Batch const& batch) override
{
BatchWriteReport report{};
BatchWriteReport report;
report.writeCount = batch.size();
auto const start = std::chrono::steady_clock::now();
for (auto const& e : batch)

View File

@@ -3,7 +3,6 @@
#include <xrpl/beast/core/SemanticVersion.h>
#include <xrpl/git/Git.h>
#include <xrpl/protocol/BuildInfo.h>
#include <xrpl/protocol/SystemParameters.h>
#include <boost/preprocessor/stringize.hpp>
@@ -81,7 +80,7 @@ getVersionString()
std::string const&
getFullVersionString()
{
static std::string const value = systemName() + "-" + getVersionString();
static std::string const value = "rippled-" + getVersionString();
return value;
}

View File

@@ -395,20 +395,10 @@ featureToName(uint256 const& f)
#pragma push_macro("XRPL_RETIRE_FIX")
#undef XRPL_RETIRE_FIX
consteval auto
enforceValidFeatureName(auto fn) -> char const*
{
static_assert(validFeatureName(fn), "Invalid feature name");
static_assert(validFeatureNameSize(fn), "Invalid feature name size");
return fn();
}
#define XRPL_FEATURE(name, supported, vote) \
uint256 const feature##name = \
registerFeature(enforceValidFeatureName([] { return #name; }), supported, vote);
uint256 const feature##name = registerFeature(#name, supported, vote);
#define XRPL_FIX(name, supported, vote) \
uint256 const fix##name = \
registerFeature(enforceValidFeatureName([] { return "fix" #name; }), supported, vote);
uint256 const fix##name = registerFeature("fix" #name, supported, vote);
// clang-format off
#define XRPL_RETIRE_FEATURE(name) \

View File

@@ -24,7 +24,7 @@ STAccount::STAccount(SField const& n) : STBase(n), value_(beast::zero), default_
{
}
STAccount::STAccount(SField const& n, Buffer const& v) : STAccount(n)
STAccount::STAccount(SField const& n, Buffer&& v) : STAccount(n)
{
if (v.empty())
return; // Zero is a valid size for a defaulted STAccount.

View File

@@ -181,7 +181,7 @@ STAmount::STAmount(SerialIter& sit, SField const& name) : STBase(name)
}
STAmount::STAmount(SField const& name, std::int64_t mantissa)
: STBase(name), mAsset(xrpIssue()), mValue(0), mOffset(0), mIsNegative(false)
: STBase(name), mAsset(xrpIssue()), mOffset(0)
{
set(mantissa);
}

View File

@@ -44,7 +44,7 @@ STArray::STArray(SerialIter& sit, SField const& f, int depth) : STBase(f)
{
while (!sit.empty())
{
int type = 0, field = 0;
int type, field;
sit.getFieldID(type, field);
if ((type == STI_ARRAY) && (field == 1))

View File

@@ -100,7 +100,7 @@ STIssue::add(Serializer& s) const
auto const& issue = asset_.get<MPTIssue>();
s.addBitString(issue.getIssuer());
s.addBitString(noAccount());
std::uint32_t sequence = 0;
std::uint32_t sequence;
memcpy(&sequence, issue.getMptID().data(), sizeof(sequence));
s.add32(sequence);
}

View File

@@ -43,14 +43,14 @@ STLedgerEntry::STLedgerEntry(Keylet const& k) : STObject(sfLedgerEntry), key_(k.
}
STLedgerEntry::STLedgerEntry(SerialIter& sit, uint256 const& index)
: STObject(sfLedgerEntry), key_(index), type_(ltANY)
: STObject(sfLedgerEntry), key_(index)
{
set(sit);
setSLEType();
}
STLedgerEntry::STLedgerEntry(STObject const& object, uint256 const& index)
: STObject(object), key_(index), type_(ltANY)
: STObject(object), key_(index)
{
setSLEType();
}

View File

@@ -179,8 +179,8 @@ partsFromString(std::string const& number)
bool negative = (match[1].matched && (match[1] == "-"));
std::uint64_t mantissa = 0;
int exponent = 0;
std::uint64_t mantissa;
int exponent;
if (!match[4].matched) // integer only
{

View File

@@ -46,7 +46,7 @@ STObject::STObject(STObject&& other)
{
}
STObject::STObject(SField const& name) : STBase(name)
STObject::STObject(SField const& name) : STBase(name), mType(nullptr)
{
}
@@ -62,7 +62,8 @@ STObject::STObject(SOTemplate const& type, SerialIter& sit, SField const& name)
applyTemplate(type); // May throw
}
STObject::STObject(SerialIter& sit, SField const& name, int depth) noexcept(false) : STBase(name)
STObject::STObject(SerialIter& sit, SField const& name, int depth) noexcept(false)
: STBase(name), mType(nullptr)
{
if (depth > 10)
Throw<std::runtime_error>("Maximum nesting depth of STObject exceeded");
@@ -215,8 +216,8 @@ STObject::set(SerialIter& sit, int depth)
// Consume data in the pipe until we run out or reach the end
while (!sit.empty())
{
int type = 0;
int field = 0;
int type;
int field;
// Get the metadata for the next field
sit.getFieldID(type, field);

View File

@@ -449,7 +449,7 @@ parseLeaf(
{
auto const str = value.asString();
std::uint64_t val = 0;
std::uint64_t val;
bool const useBase10 = field.shouldMeta(SField::sMD_BaseTen);

View File

@@ -211,20 +211,6 @@ STTx::getSeqValue() const
return getSeqProxy().value();
}
AccountID
STTx::getFeePayer() const
{
// If sfDelegate is present, the delegate account is the payer
// note: if a delegate is specified, its authorization to act on behalf of the account is
// enforced in `Transactor::checkPermission`
// cryptographic signature validity is checked separately (e.g., in `Transactor::checkSign`)
if (isFieldPresent(sfDelegate))
return getAccountID(sfDelegate);
// Default payer
return getAccountID(sfAccount);
}
void
STTx::sign(
PublicKey const& publicKey,
@@ -365,7 +351,7 @@ STTx::getMetaSQL(std::uint32_t inLedger, std::string const& escapedMetaData) con
{
Serializer s;
add(s);
return getMetaSQL(s, inLedger, TxnSql::txnSqlValidated, escapedMetaData);
return getMetaSQL(s, inLedger, txnSqlValidated, escapedMetaData);
}
// VFALCO This could be a free function elsewhere
@@ -373,7 +359,7 @@ std::string
STTx::getMetaSQL(
Serializer rawTxn,
std::uint32_t inLedger,
TxnSql status,
char status,
std::string const& escapedMetaData) const
{
static boost::format bfTrans("('%s', '%s', '%s', '%d', '%d', '%c', %s, %s)");
@@ -384,8 +370,8 @@ STTx::getMetaSQL(
return str(
boost::format(bfTrans) % to_string(getTransactionID()) % format->getName() %
toBase58(getAccountID(sfAccount)) % getFieldU32(sfSequence) % inLedger %
safe_cast<char>(status) % rTxn % escapedMetaData);
toBase58(getAccountID(sfAccount)) % getFieldU32(sfSequence) % inLedger % status % rTxn %
escapedMetaData);
}
static Expected<void, std::string>
@@ -708,9 +694,9 @@ invalidMPTAmountInTx(STObject const& tx)
{
if (auto const& field = tx.peekAtField(e.sField());
(field.getSType() == STI_AMOUNT &&
safe_downcast<STAmount const&>(field).holds<MPTIssue>()) ||
static_cast<STAmount const&>(field).holds<MPTIssue>()) ||
(field.getSType() == STI_ISSUE &&
safe_downcast<STIssue const&>(field).holds<MPTIssue>()))
static_cast<STIssue const&>(field).holds<MPTIssue>()))
{
if (e.supportMPT() != soeMPTSupported)
return true;

View File

@@ -74,7 +74,7 @@ deriveDeterministicRootKey(Seed const& seed)
// buf |----------------|----|
// | seed | seq|
std::array<std::uint8_t, 20> buf{};
std::array<std::uint8_t, 20> buf;
std::copy(seed.begin(), seed.end(), buf.begin());
// The odds that this loop executes more than once are negligible
@@ -119,7 +119,7 @@ class Generator
{
private:
uint256 root_;
std::array<std::uint8_t, 33> generator_{};
std::array<std::uint8_t, 33> generator_;
uint256
calculateTweak(std::uint32_t seq) const
@@ -133,7 +133,7 @@ private:
// buf |---------------------------------|----|----|
// | generator | seq| cnt|
std::array<std::uint8_t, 41> buf{};
std::array<std::uint8_t, 41> buf;
std::copy(generator_.begin(), generator_.end(), buf.begin());
copy_uint32(buf.data() + 33, seq);

View File

@@ -46,7 +46,7 @@ Seed::Seed(uint128 const& seed)
Seed
randomSeed()
{
std::array<std::uint8_t, 16> buffer{};
std::array<std::uint8_t, 16> buffer;
beast::rngfill(buffer.data(), buffer.size(), crypto_prng());
Seed seed(makeSlice(buffer));
secure_erase(buffer.data(), buffer.size());

View File

@@ -206,7 +206,7 @@ Serializer::addVL(void const* ptr, int len)
int
Serializer::addEncoded(int length)
{
std::array<std::uint8_t, 4> bytes{};
std::array<std::uint8_t, 4> bytes;
int numBytes = 0;
if (length <= 192)
@@ -466,7 +466,7 @@ int
SerialIter::getVLDataLength()
{
int b1 = get8();
int datLen = 0;
int datLen;
int lenLen = Serializer::decodeLengthLength(b1);
if (lenLen == 1)
{

View File

@@ -329,7 +329,7 @@ decodeBase58Token(std::string const& s, TokenType type)
return {};
// And the checksum must as well.
std::array<char, 4> guard{};
std::array<char, 4> guard;
checksum(guard.data(), ret.data(), ret.size() - guard.size());
if (!std::equal(guard.rbegin(), guard.rend(), ret.rbegin()))
return {};
@@ -610,7 +610,7 @@ encodeBase58Token(
std::span<std::uint8_t> out)
{
constexpr std::size_t tmpBufSize = 128;
std::array<std::uint8_t, tmpBufSize> buf{};
std::array<std::uint8_t, tmpBufSize> buf;
if (input.size() > tmpBufSize - 5)
{
return Unexpected(TokenCodecErrc::inputTooLarge);
@@ -637,7 +637,7 @@ encodeBase58Token(
B58Result<std::span<std::uint8_t>>
decodeBase58Token(TokenType type, std::string_view s, std::span<std::uint8_t> outBuf)
{
std::array<std::uint8_t, 64> tmpBuf{};
std::array<std::uint8_t, 64> tmpBuf;
auto const decodeResult = detail::b58_to_b256_be(s, std::span(tmpBuf.data(), tmpBuf.size()));
if (!decodeResult)
@@ -654,7 +654,7 @@ decodeBase58Token(TokenType type, std::string_view s, std::span<std::uint8_t> ou
return Unexpected(TokenCodecErrc::mismatchedTokenType);
// And the checksum must as well.
std::array<std::uint8_t, 4> guard{};
std::array<std::uint8_t, 4> guard;
checksum(guard.data(), ret.data(), ret.size() - guard.size());
if (!std::equal(guard.rbegin(), guard.rend(), ret.rbegin()))
{

View File

@@ -17,7 +17,7 @@ getHTTPHeaderTimestamp()
// sense. There's no point in doing all this work if this function
// gets called multiple times a second.
char buffer[96];
time_t now = 0;
time_t now;
time(&now);
struct tm now_gmt{};
#ifndef _MSC_VER
@@ -68,7 +68,6 @@ HTTPReply(int nStatus, std::string const& content, Json::Output const& output, b
return;
}
// NOLINTNEXTLINE(bugprone-switch-missing-default-case)
switch (nStatus)
{
case 200:

View File

@@ -98,7 +98,7 @@ populate(
while (std::getline(ss, ip, ','))
{
boost::algorithm::trim(ip);
bool v4 = false;
bool v4;
boost::asio::ip::network_v4 v4Net;
boost::asio::ip::network_v6 v6Net;

View File

@@ -54,7 +54,7 @@ initStateDB(soci::session& session, BasicConfig const& config, std::string const
LedgerIndex
getCanDelete(soci::session& session)
{
LedgerIndex seq = 0;
LedgerIndex seq;
session << "SELECT CanDeleteSeq FROM CanDelete WHERE Key = 1;", soci::into(seq);
;
return seq;

View File

@@ -25,7 +25,7 @@ doVacuumDB(DatabaseCon::Setup const& setup, beast::Journal j)
auto txnDB = std::make_unique<DatabaseCon>(setup, TxDBName, setup.txPragma, TxDBInit, j);
auto& session = txnDB->getSession();
std::uint32_t pageSize = 0;
std::uint32_t pageSize;
// Only the most trivial databases will fit in memory on typical
// (recommended) hardware. Force temp files to be written to disk

View File

@@ -1,6 +1,5 @@
#include <xrpl/basics/TaggedCache.ipp>
#include <xrpl/basics/contract.h>
#include <xrpl/basics/safe_cast.h>
#include <xrpl/shamap/SHAMap.h>
#include <xrpl/shamap/SHAMapAccountStateLeafNode.h>
#include <xrpl/shamap/SHAMapNodeID.h>
@@ -123,7 +122,7 @@ SHAMap::walkTowardsKey(uint256 const& id, SharedPtrNodeStack* stack) const
if (stack != nullptr)
stack->push({inNode, nodeID});
return safe_downcast<SHAMapLeafNode*>(inNode.get());
return static_cast<SHAMapLeafNode*>(inNode.get());
}
SHAMapLeafNode*
@@ -472,7 +471,7 @@ SHAMap::onlyBelow(SHAMapTreeNode* node) const
while (!node->isLeaf())
{
SHAMapTreeNode* nextNode = nullptr;
auto inner = safe_downcast<SHAMapInnerNode*>(node);
auto inner = static_cast<SHAMapInnerNode*>(node);
for (int i = 0; i < branchFactor; ++i)
{
if (!inner->isEmptyBranch(i))
@@ -497,7 +496,7 @@ SHAMap::onlyBelow(SHAMapTreeNode* node) const
// An inner node must have at least one leaf
// below it, unless it's the root_
auto const leaf = safe_downcast<SHAMapLeafNode const*>(node);
auto const leaf = static_cast<SHAMapLeafNode const*>(node);
XRPL_ASSERT(
leaf->peekItem() || (leaf == root_.get()), "xrpl::SHAMap::onlyBelow : valid inner node");
return leaf->peekItem();
@@ -579,7 +578,7 @@ SHAMap::upper_bound(uint256 const& id) const
auto [node, nodeID] = stack.top();
if (node->isLeaf())
{
auto leaf = safe_downcast<SHAMapLeafNode*>(node.get());
auto leaf = static_cast<SHAMapLeafNode*>(node.get());
if (leaf->peekItem()->key() > id)
return const_iterator(this, leaf->peekItem().get(), std::move(stack));
}
@@ -612,7 +611,7 @@ SHAMap::lower_bound(uint256 const& id) const
auto [node, nodeID] = stack.top();
if (node->isLeaf())
{
auto leaf = safe_downcast<SHAMapLeafNode*>(node.get());
auto leaf = static_cast<SHAMapLeafNode*>(node.get());
if (leaf->peekItem()->key() < id)
return const_iterator(this, leaf->peekItem().get(), std::move(stack));
}
@@ -663,10 +662,9 @@ SHAMap::delItem(uint256 const& id)
SHAMapNodeType type = leaf->getType();
using TreeNodeType = intr_ptr::SharedPtr<SHAMapTreeNode>;
// What gets attached to the end of the chain (For now, nothing, since we deleted the leaf)
TreeNodeType prevNode;
// What gets attached to the end of the chain
// (For now, nothing, since we deleted the leaf)
intr_ptr::SharedPtr<SHAMapTreeNode> prevNode;
while (!stack.empty())
{
@@ -675,12 +673,7 @@ SHAMap::delItem(uint256 const& id)
stack.pop();
node = unshareNode(std::move(node), nodeID);
node->setChild(
selectBranch(nodeID, id), std::move(prevNode)); // NOLINT(bugprone-use-after-move)
XRPL_ASSERT(
not prevNode, // NOLINT(bugprone-use-after-move)
"xrpl::SHAMap::delItem : prevNode should be nullptr after std::move");
node->setChild(selectBranch(nodeID, id), std::move(prevNode));
if (!nodeID.isRoot())
{
@@ -690,9 +683,7 @@ SHAMap::delItem(uint256 const& id)
if (bc == 0)
{
// no children below this branch
//
// Note: This is unnecessary due to the std::move above but left here for safety
prevNode = TreeNodeType{};
prevNode.reset();
}
else if (bc == 1)
{
@@ -705,7 +696,7 @@ SHAMap::delItem(uint256 const& id)
{
if (!node->isEmptyBranch(i))
{
node->setChild(i, TreeNodeType{});
node->setChild(i, intr_ptr::SharedPtr<SHAMapTreeNode>{});
break;
}
}
@@ -773,7 +764,7 @@ SHAMap::addGiveItem(SHAMapNodeType type, boost::intrusive_ptr<SHAMapItem const>
node = intr_ptr::make_shared<SHAMapInnerNode>(node->cowid());
unsigned int b1 = 0, b2 = 0;
unsigned int b1, b2;
while ((b1 = selectBranch(nodeID, tag)) == (b2 = selectBranch(nodeID, otherItem->key())))
{
@@ -788,7 +779,7 @@ SHAMap::addGiveItem(SHAMapNodeType type, boost::intrusive_ptr<SHAMapItem const>
// we can add the two leaf nodes here
XRPL_ASSERT(node->isInner(), "xrpl::SHAMap::addGiveItem : node is inner");
auto inner = safe_downcast<SHAMapInnerNode*>(node.get());
auto inner = static_cast<SHAMapInnerNode*>(node.get());
inner->setChild(b1, makeTypedLeaf(type, std::move(item), cowid_));
inner->setChild(b2, makeTypedLeaf(type, std::move(otherItem), cowid_));
}
@@ -1097,7 +1088,7 @@ SHAMap::dump(bool hash) const
if (node->isInner())
{
auto inner = safe_downcast<SHAMapInnerNode*>(node);
auto inner = static_cast<SHAMapInnerNode*>(node);
for (int i = 0; i < branchFactor; ++i)
{
if (!inner->isEmptyBranch(i))

View File

@@ -1,6 +1,5 @@
#include <xrpl/basics/IntrusivePointer.ipp>
#include <xrpl/basics/contract.h>
#include <xrpl/basics/safe_cast.h>
#include <xrpl/shamap/SHAMap.h>
#include <array>
@@ -40,7 +39,7 @@ SHAMap::walkBranch(
if (node->isInner())
{
// This is an inner node, add all non-empty branches
auto inner = safe_downcast<SHAMapInnerNode*>(node);
auto inner = static_cast<SHAMapInnerNode*>(node);
for (int i = 0; i < 16; ++i)
if (!inner->isEmptyBranch(i))
nodeStack.push({descendThrow(inner, i)});
@@ -48,7 +47,7 @@ SHAMap::walkBranch(
else
{
// This is a leaf node, process its item
auto item = safe_downcast<SHAMapLeafNode*>(node)->peekItem();
auto item = static_cast<SHAMapLeafNode*>(node)->peekItem();
if (emptyBranch || (item->key() != otherMapItem->key()))
{
@@ -133,8 +132,8 @@ SHAMap::compare(SHAMap const& otherMap, Delta& differences, int maxCount) const
if (ourNode->isLeaf() && otherNode->isLeaf())
{
// two leaves
auto ours = safe_downcast<SHAMapLeafNode*>(ourNode);
auto other = safe_downcast<SHAMapLeafNode*>(otherNode);
auto ours = static_cast<SHAMapLeafNode*>(ourNode);
auto other = static_cast<SHAMapLeafNode*>(otherNode);
if (ours->peekItem()->key() == other->peekItem()->key())
{
if (ours->peekItem()->slice() != other->peekItem()->slice())
@@ -162,22 +161,22 @@ SHAMap::compare(SHAMap const& otherMap, Delta& differences, int maxCount) const
}
else if (ourNode->isInner() && otherNode->isLeaf())
{
auto ours = safe_downcast<SHAMapInnerNode*>(ourNode);
auto other = safe_downcast<SHAMapLeafNode*>(otherNode);
auto ours = static_cast<SHAMapInnerNode*>(ourNode);
auto other = static_cast<SHAMapLeafNode*>(otherNode);
if (!walkBranch(ours, other->peekItem(), true, differences, maxCount))
return false;
}
else if (ourNode->isLeaf() && otherNode->isInner())
{
auto ours = safe_downcast<SHAMapLeafNode*>(ourNode);
auto other = safe_downcast<SHAMapInnerNode*>(otherNode);
auto ours = static_cast<SHAMapLeafNode*>(ourNode);
auto other = static_cast<SHAMapInnerNode*>(otherNode);
if (!otherMap.walkBranch(other, ours->peekItem(), false, differences, maxCount))
return false;
}
else if (ourNode->isInner() && otherNode->isInner())
{
auto ours = safe_downcast<SHAMapInnerNode*>(ourNode);
auto other = safe_downcast<SHAMapInnerNode*>(otherNode);
auto ours = static_cast<SHAMapInnerNode*>(ourNode);
auto other = static_cast<SHAMapInnerNode*>(otherNode);
for (int i = 0; i < 16; ++i)
if (ours->getChildHash(i) != other->getChildHash(i))
{

View File

@@ -20,7 +20,7 @@ SHAMapInnerNode::~SHAMapInnerNode() = default;
void
SHAMapInnerNode::partialDestructor()
{
intr_ptr::SharedPtr<SHAMapTreeNode>* children = nullptr;
intr_ptr::SharedPtr<SHAMapTreeNode>* children;
// structured bindings can't be captured in c++ 17; use tie instead
std::tie(std::ignore, std::ignore, children) = hashesAndChildren_.getHashesAndChildren();
iterNonEmptyChildIndexes([&](auto branchNum, auto indexNum) { children[indexNum].reset(); });
@@ -61,8 +61,8 @@ SHAMapInnerNode::clone(std::uint32_t cowid) const
p->hash_ = hash_;
p->isBranch_ = isBranch_;
p->fullBelowGen_ = fullBelowGen_;
SHAMapHash *cloneHashes = nullptr, *thisHashes = nullptr;
intr_ptr::SharedPtr<SHAMapTreeNode>*cloneChildren = nullptr, *thisChildren = nullptr;
SHAMapHash *cloneHashes, *thisHashes;
intr_ptr::SharedPtr<SHAMapTreeNode>*cloneChildren, *thisChildren;
// structured bindings can't be captured in c++ 17; use tie instead
std::tie(std::ignore, cloneHashes, cloneChildren) =
p->hashesAndChildren_.getHashesAndChildren();
@@ -185,8 +185,8 @@ SHAMapInnerNode::updateHash()
void
SHAMapInnerNode::updateHashDeep()
{
SHAMapHash* hashes = nullptr;
intr_ptr::SharedPtr<SHAMapTreeNode>* children = nullptr;
SHAMapHash* hashes;
intr_ptr::SharedPtr<SHAMapTreeNode>* children;
// structured bindings can't be captured in c++ 17; use tie instead
std::tie(std::ignore, hashes, children) = hashesAndChildren_.getHashesAndChildren();
iterNonEmptyChildIndexes([&](auto branchNum, auto indexNum) {

View File

@@ -1,5 +1,4 @@
#include <xrpl/basics/random.h>
#include <xrpl/basics/safe_cast.h>
#include <xrpl/shamap/SHAMap.h>
#include <xrpl/shamap/SHAMapLeafNode.h>
#include <xrpl/shamap/SHAMapSyncFilter.h>
@@ -13,7 +12,7 @@ SHAMap::visitLeaves(
{
visitNodes([&leafFunction](SHAMapTreeNode& node) {
if (!node.isInner())
leafFunction(safe_downcast<SHAMapLeafNode&>(node).peekItem());
leafFunction(static_cast<SHAMapLeafNode&>(node).peekItem());
return true;
});
}
@@ -105,7 +104,7 @@ SHAMap::visitDifferences(
using StackEntry = std::pair<SHAMapInnerNode*, SHAMapNodeID>;
std::stack<StackEntry, std::vector<StackEntry>> stack;
stack.push({safe_downcast<SHAMapInnerNode*>(root_.get()), SHAMapNodeID{}});
stack.push({static_cast<SHAMapInnerNode*>(root_.get()), SHAMapNodeID{}});
while (!stack.empty())
{
@@ -128,12 +127,12 @@ SHAMap::visitDifferences(
if (next->isInner())
{
if (!have || !have->hasInnerNode(childID, childHash))
stack.push({safe_downcast<SHAMapInnerNode*>(next), childID});
stack.push({static_cast<SHAMapInnerNode*>(next), childID});
}
else if (
!have ||
!have->hasLeafNode(
safe_downcast<SHAMapLeafNode*>(next)->peekItem()->key(), childHash))
static_cast<SHAMapLeafNode*>(next)->peekItem()->key(), childHash))
{
if (!function(*next))
return;
@@ -202,13 +201,12 @@ SHAMap::gmn_ProcessNodes(MissingNodes& mn, MissingNodes::StackEntry& se)
if (--mn.max_ <= 0)
return;
}
else if (
d->isInner() && !safe_downcast<SHAMapInnerNode*>(d)->isFullBelow(mn.generation_))
else if (d->isInner() && !static_cast<SHAMapInnerNode*>(d)->isFullBelow(mn.generation_))
{
mn.stack_.push(se);
// Switch to processing the child node
node = safe_downcast<SHAMapInnerNode*>(d);
node = static_cast<SHAMapInnerNode*>(d);
nodeID = nodeID.getChildNodeID(branch);
firstChild = rand_int(255);
currentChild = 0;
@@ -307,7 +305,7 @@ SHAMap::getMissingNodes(int max, SHAMapSyncFilter* filter)
// that the two threads will produce different request sets (which is
// more efficient than sending identical requests).
MissingNodes::StackEntry pos{
safe_downcast<SHAMapInnerNode*>(root_.get()), SHAMapNodeID(), rand_int(255), 0, true};
static_cast<SHAMapInnerNode*>(root_.get()), SHAMapNodeID(), rand_int(255), 0, true};
auto& node = std::get<0>(pos);
auto& nextChild = std::get<3>(pos);
auto& fullBelow = std::get<4>(pos);
@@ -401,7 +399,7 @@ SHAMap::getNodeFat(
while (node && node->isInner() && (nodeID.getDepth() < wanted.getDepth()))
{
int branch = selectBranch(nodeID, wanted.getNodeID());
auto inner = safe_downcast<SHAMapInnerNode*>(node);
auto inner = static_cast<SHAMapInnerNode*>(node);
if (inner->isEmptyBranch(branch))
return false;
node = descendThrow(inner, branch);
@@ -415,7 +413,7 @@ SHAMap::getNodeFat(
return false;
}
if (node->isInner() && safe_downcast<SHAMapInnerNode*>(node)->isEmpty())
if (node->isInner() && static_cast<SHAMapInnerNode*>(node)->isEmpty())
{
JLOG(journal_.warn()) << "peer requests empty node";
return false;
@@ -440,7 +438,7 @@ SHAMap::getNodeFat(
{
// We descend inner nodes with only a single child
// without decrementing the depth
auto inner = safe_downcast<SHAMapInnerNode*>(node);
auto inner = static_cast<SHAMapInnerNode*>(node);
int bc = inner->getBranchCount();
if ((depth > 0) || (bc == 1))
@@ -532,12 +530,12 @@ SHAMap::addKnownNode(SHAMapNodeID const& node, Slice const& rawNode, SHAMapSyncF
auto currNode = root_.get();
while (currNode->isInner() &&
!safe_downcast<SHAMapInnerNode*>(currNode)->isFullBelow(generation) &&
!static_cast<SHAMapInnerNode*>(currNode)->isFullBelow(generation) &&
(currNodeID.getDepth() < node.getDepth()))
{
int const branch = selectBranch(currNodeID, node.getNodeID());
XRPL_ASSERT(branch >= 0, "xrpl::SHAMap::addKnownNode : valid branch");
auto inner = safe_downcast<SHAMapInnerNode*>(currNode);
auto inner = static_cast<SHAMapInnerNode*>(currNode);
if (inner->isEmptyBranch(branch))
{
JLOG(journal_.warn()) << "Add known node for empty branch" << node;
@@ -572,7 +570,7 @@ SHAMap::addKnownNode(SHAMapNodeID const& node, Slice const& rawNode, SHAMapSyncF
if (newNode->isLeaf())
{
auto const& actualKey =
safe_downcast<SHAMapLeafNode const*>(newNode.get())->peekItem()->key();
static_cast<SHAMapLeafNode const*>(newNode.get())->peekItem()->key();
// Validate that this leaf belongs at the target position
auto const expectedNodeID = SHAMapNodeID::createID(node.getDepth(), actualKey);
@@ -654,8 +652,8 @@ SHAMap::deepCompare(SHAMap& other) const
{
if (!otherNode->isLeaf())
return false;
auto& nodePeek = safe_downcast<SHAMapLeafNode*>(node)->peekItem();
auto& otherNodePeek = safe_downcast<SHAMapLeafNode*>(otherNode)->peekItem();
auto& nodePeek = static_cast<SHAMapLeafNode*>(node)->peekItem();
auto& otherNodePeek = static_cast<SHAMapLeafNode*>(otherNode)->peekItem();
if (nodePeek->key() != otherNodePeek->key())
return false;
if (nodePeek->slice() != otherNodePeek->slice())
@@ -665,8 +663,8 @@ SHAMap::deepCompare(SHAMap& other) const
{
if (!otherNode->isInner())
return false;
auto node_inner = safe_downcast<SHAMapInnerNode*>(node);
auto other_inner = safe_downcast<SHAMapInnerNode*>(otherNode);
auto node_inner = static_cast<SHAMapInnerNode*>(node);
auto other_inner = static_cast<SHAMapInnerNode*>(otherNode);
for (int i = 0; i < 16; ++i)
{
if (node_inner->isEmptyBranch(i))
@@ -706,7 +704,7 @@ SHAMap::hasInnerNode(SHAMapNodeID const& targetNodeID, SHAMapHash const& targetN
while (node->isInner() && (nodeID.getDepth() < targetNodeID.getDepth()))
{
int branch = selectBranch(nodeID, targetNodeID.getNodeID());
auto inner = safe_downcast<SHAMapInnerNode*>(node);
auto inner = static_cast<SHAMapInnerNode*>(node);
if (inner->isEmptyBranch(branch))
return false;
@@ -731,7 +729,7 @@ SHAMap::hasLeafNode(uint256 const& tag, SHAMapHash const& targetNodeHash) const
do
{
int branch = selectBranch(nodeID, tag);
auto inner = safe_downcast<SHAMapInnerNode*>(node);
auto inner = static_cast<SHAMapInnerNode*>(node);
if (inner->isEmptyBranch(branch))
return false; // Dead end, node must not be here
@@ -802,7 +800,7 @@ SHAMap::verifyProofPath(uint256 const& rootHash, uint256 const& key, std::vector
if (node->isInner())
{
auto nodeId = SHAMapNodeID::createID(depth, key);
hash = safe_downcast<SHAMapInnerNode*>(node.get())
hash = static_cast<SHAMapInnerNode*>(node.get())
->getChildHash(selectBranch(nodeId, key));
}
else

View File

@@ -352,7 +352,8 @@ Transactor::checkFee(PreclaimContext const& ctx, XRPAmount baseFee)
if (feePaid == beast::zero)
return tesSUCCESS;
auto const id = ctx.tx.getFeePayer();
auto const id = ctx.tx.isFieldPresent(sfDelegate) ? ctx.tx.getAccountID(sfDelegate)
: ctx.tx.getAccountID(sfAccount);
auto const sle = ctx.view.read(keylet::account(id));
if (!sle)
return terNO_ACCOUNT;
@@ -381,18 +382,32 @@ Transactor::payFee()
{
auto const feePaid = ctx_.tx[sfFee].xrp();
auto const feePayer = ctx_.tx.getFeePayer();
auto const sle = view().peek(keylet::account(feePayer));
if (!sle)
return tefINTERNAL; // LCOV_EXCL_LINE
if (ctx_.tx.isFieldPresent(sfDelegate))
{
// Delegated transactions are paid by the delegated account.
auto const delegate = ctx_.tx.getAccountID(sfDelegate);
auto const delegatedSle = view().peek(keylet::account(delegate));
if (!delegatedSle)
return tefINTERNAL; // LCOV_EXCL_LINE
// Deduct the fee, so it's not available during the transaction.
// Will only write the account back if the transaction succeeds.
sle->setFieldAmount(sfBalance, sle->getFieldAmount(sfBalance) - feePaid);
if (feePayer != account_)
view().update(sle); // done in `apply()` for the account
delegatedSle->setFieldAmount(sfBalance, delegatedSle->getFieldAmount(sfBalance) - feePaid);
view().update(delegatedSle);
}
else
{
auto const sle = view().peek(keylet::account(account_));
if (!sle)
return tefINTERNAL; // LCOV_EXCL_LINE
// Deduct the fee, so it's not available during the transaction.
// Will only write the account back if the transaction succeeds.
mSourceBalance -= feePaid;
sle->setFieldAmount(sfBalance, mSourceBalance);
// VFALCO Should we call view().rawDestroyXRP() here as well?
}
// VFALCO Should we call view().rawDestroyXRP() here as well?
return tesSUCCESS;
}
@@ -591,7 +606,8 @@ Transactor::apply()
if (sle)
{
preFeeBalance_ = STAmount{(*sle)[sfBalance]}.xrp();
mPriorBalance = STAmount{(*sle)[sfBalance]}.xrp();
mSourceBalance = mPriorBalance;
TER result = consumeSeqProxy(sle);
if (result != tesSUCCESS)
@@ -1007,7 +1023,9 @@ Transactor::reset(XRPAmount fee)
if (!txnAcct)
return {tefINTERNAL, beast::zero};
auto const payerSle = view().peek(keylet::account(ctx_.tx.getFeePayer()));
auto const payerSle = ctx_.tx.isFieldPresent(sfDelegate)
? view().peek(keylet::account(ctx_.tx.getAccountID(sfDelegate)))
: txnAcct;
if (!payerSle)
return {tefINTERNAL, beast::zero}; // LCOV_EXCL_LINE

View File

@@ -149,7 +149,7 @@ applyBatchTransactions(
auto const parentBatchId = batchTxn.getTransactionID();
auto const mode = batchTxn.getFlags();
auto applyOneTransaction = [&registry, &j, &parentBatchId, &batchView](STTx const& tx) {
auto applyOneTransaction = [&registry, &j, &parentBatchId, &batchView](STTx&& tx) {
OpenView perTxBatchView(batch_view, batchView);
auto const ret = apply(registry, perTxBatchView, parentBatchId, tx, tapBATCH, j);

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