diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c34f89397d..49ecd192b7b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -73,6 +73,7 @@ set(SECP256K1_INSTALL TRUE) add_subdirectory(external/secp256k1) add_library(secp256k1::secp256k1 ALIAS secp256k1) add_subdirectory(external/ed25519-donna) +add_subdirectory(external/antithesis-sdk) find_package(gRPC REQUIRED) find_package(lz4 REQUIRED) # Target names with :: are not allowed in a generator expression. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ceca1eaa6fc..0609cd7f2e5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -343,6 +343,68 @@ pip3 install pre-commit pre-commit install ``` +## Contracts and instrumentation + +We are using [Antithesis](https://antithesis.com/) for continuous fuzzing, +and keep a copy of [Antithesis C++ SDK](https://github.com/antithesishq/antithesis-sdk-cpp/) +in `external/antithesis-sdk`. One of the aims of fuzzing is to identify bugs +by finding external conditions which cause contracts violations inside `rippled`. +The contracts are expressed as `ASSERT` or `UNREACHABLE` (defined in +`include/xrpl/beast/utility/instrumentation.h`), which are effectively (outside +of Antithesis) wrappers for `assert(...)` with added name. The purpose of name +is to provide contracts with stable identity which does not rely on line numbers. + +When `rippled` is built with the Antithesis instrumentation enabled +(using `voidstar` CMake option) and ran on the Antithesis platform, the +contracts become +[test properties](https://antithesis.com/docs/using_antithesis/properties.html); +otherwise they are just like a regular `assert`. +To learn more about Antithesis, see +[How Antithesis Works](https://antithesis.com/docs/introduction/how_antithesis_works.html) +and [C++ SDK](https://antithesis.com/docs/using_antithesis/sdk/cpp/overview.html#) + +We continue to use the old style `assert` or `assert(false)` in certain +locations, where the reporting of contract violations on the Antithesis +platform is either not possible or not useful. + +For this reason: +* The locations where `assert` or `assert(false)` contracts should continue to be used: + * `constexpr` functions + * unit tests i.e. files under `src/test` + * unit tests-related modules (files under `beast/test` and `beast/unit_test`) +* Outside of the listed locations, do not use `assert`; use `ASSERT` instead, + giving it unique name, with the short description of the contract. +* Outside of the listed locations, do not use `assert(false)`; use + `UNREACHABLE` instead, giving it unique name, with the description of the + condition being violated +* The contract name should start with a full name (including scope) of the + function, optionally a named lambda, followed by a colon ` : ` and a brief + (typically at most five words) description. `UNREACHABLE` contracts + can use slightly longer descriptions. If there are multiple overloads of the + function, use common sense to balance both brevity and unambiguity of the + function name. NOTE: the purpose of name is to provide stable means of + unique identification of every contract; for this reason try to avoid elements + which can change in some obvious refactors or when reinforcing the condition. +* Contract description typically (except for `UNREACHABLE`) should describe the + _expected_ condition, as in "I assert that _expected_ is true". +* Contract description for `UNREACHABLE` should describe the _unexpected_ + situation which caused the line to have been reached. +* Example good name for an + `UNREACHABLE` macro `"Json::operator==(Value, Value) : invalid type"`; example + good name for an `ASSERT` macro `"Json::Value::asCString : valid type"`. +* Example **bad** name + `"RFC1751::insert(char* s, int x, int start, int length) : length is greater than or equal zero"` + (missing namespace, unnecessary full function signature, description too verbose). + Good name: `"ripple::RFC1751::insert : minimum length"`. +* In **few** well-justified cases a non-standard name can be used, in which case a + comment should be placed to explain the rationale (example in `contract.cpp`) +* Do **not** rename a contract without a good reason (e.g. the name no longer + reflects the location or the condition being checked) +* Do not use `std::unreachable` +* Do not put contracts where they can be violated by an external condition + (e.g. timing, data payload before mandatory validation etc.) as this creates + bogus bug reports (and causes crashes of Debug builds) + ## Unit Tests To execute all unit tests: diff --git a/cmake/RippledCompiler.cmake b/cmake/RippledCompiler.cmake index 43afc628bc3..7485605d950 100644 --- a/cmake/RippledCompiler.cmake +++ b/cmake/RippledCompiler.cmake @@ -120,7 +120,7 @@ else () target_link_libraries (common INTERFACE -rdynamic - $<$:-Wl,-z,relro,-z,now> + $<$:-Wl,-z,relro,-z,now,--build-id> # link to static libc/c++ iff: # * static option set and # * NOT APPLE (AppleClang does not support static libc/c++) and @@ -131,6 +131,17 @@ else () >) endif () +# Antithesis instrumentation will only be built and deployed using machines running Linux. +if (voidstar) + if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug") + message(FATAL_ERROR "Antithesis instrumentation requires Debug build type, aborting...") + elseif (NOT is_linux) + message(FATAL_ERROR "Antithesis instrumentation requires Linux, aborting...") + elseif (NOT (is_clang AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 16.0)) + message(FATAL_ERROR "Antithesis instrumentation requires Clang version 16 or later, aborting...") + endif () +endif () + if (use_mold) # use mold linker if available execute_process ( diff --git a/cmake/RippledCore.cmake b/cmake/RippledCore.cmake index 3b850354ed4..201384c3fcb 100644 --- a/cmake/RippledCore.cmake +++ b/cmake/RippledCore.cmake @@ -74,6 +74,7 @@ target_compile_definitions(xrpl.libxrpl target_compile_options(xrpl.libxrpl PUBLIC $<$:-Wno-maybe-uninitialized> + $<$:-DENABLE_VOIDSTAR> ) target_link_libraries(xrpl.libxrpl @@ -89,6 +90,7 @@ target_link_libraries(xrpl.libxrpl secp256k1::secp256k1 xrpl.libpb xxHash::xxhash + $<$:antithesis-sdk-cpp> ) if(xrpld) @@ -129,6 +131,19 @@ if(xrpld) target_compile_definitions(rippled PRIVATE RIPPLED_RUNNING_IN_CI) endif () + if(voidstar) + target_compile_options(rippled + PRIVATE + -fsanitize-coverage=trace-pc-guard + ) + # rippled requires access to antithesis-sdk-cpp implementation file + # antithesis_instrumentation.h, which is not exported as INTERFACE + target_include_directories(rippled + PRIVATE + ${CMAKE_SOURCE_DIR}/external/antithesis-sdk + ) + endif() + # any files that don't play well with unity should be added here if(tests) set_source_files_properties( diff --git a/cmake/RippledInstall.cmake b/cmake/RippledInstall.cmake index 3199c9a19b8..229cc9b1c8a 100644 --- a/cmake/RippledInstall.cmake +++ b/cmake/RippledInstall.cmake @@ -10,6 +10,7 @@ install ( ripple_boost xrpl.libpb xrpl.libxrpl + antithesis-sdk-cpp EXPORT RippleExports LIBRARY DESTINATION lib ARCHIVE DESTINATION lib diff --git a/cmake/RippledSettings.cmake b/cmake/RippledSettings.cmake index b81843cd5b5..3eeebed428c 100644 --- a/cmake/RippledSettings.cmake +++ b/cmake/RippledSettings.cmake @@ -18,6 +18,9 @@ if(unity) set(CMAKE_UNITY_BUILD_BATCH_SIZE 15 CACHE STRING "") endif() endif() +if(is_clang AND is_linux) + option(voidstar "Enable Antithesis instrumentation." OFF) +endif() if(is_gcc OR is_clang) option(coverage "Generates coverage info." OFF) option(profile "Add profiling flags" OFF) diff --git a/external/README.md b/external/README.md index 25ae577ba58..c810539fd7d 100644 --- a/external/README.md +++ b/external/README.md @@ -6,6 +6,7 @@ The Conan recipes include patches we have not yet pushed upstream. | Folder | Upstream | Description | |:----------------|:---------------------------------------------|:------------| +| `antithesis-sdk`| [Project](https://github.com/antithesishq/antithesis-sdk-cpp/) | [Antithesis](https://antithesis.com/docs/using_antithesis/sdk/cpp/overview.html) SDK for C++ | | `ed25519-donna` | [Project](https://github.com/floodyberry/ed25519-donna) | [Ed25519](http://ed25519.cr.yp.to/) digital signatures | | `rocksdb` | [Recipe](https://github.com/conan-io/conan-center-index/tree/master/recipes/rocksdb) | Fast key/value database. (Supports rotational disks better than NuDB.) | | `secp256k1` | [Project](https://github.com/bitcoin-core/secp256k1) | ECDSA digital signatures using the **secp256k1** curve | diff --git a/external/antithesis-sdk/.clang-format b/external/antithesis-sdk/.clang-format new file mode 100644 index 00000000000..e871ed18b43 --- /dev/null +++ b/external/antithesis-sdk/.clang-format @@ -0,0 +1,3 @@ +--- +DisableFormat: true +SortIncludes: false diff --git a/external/antithesis-sdk/CMakeLists.txt b/external/antithesis-sdk/CMakeLists.txt new file mode 100644 index 00000000000..b7fa22de107 --- /dev/null +++ b/external/antithesis-sdk/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.25) + +# Note, version set explicitly by rippled project +project(antithesis-sdk-cpp VERSION 0.4.2 LANGUAGES CXX) + +add_library(antithesis-sdk-cpp INTERFACE antithesis_sdk.h) + +# Note, both sections below created by rippled project +target_include_directories(antithesis-sdk-cpp INTERFACE + $ + $ +) + +install( + FILES antithesis_sdk.h + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" +) diff --git a/external/antithesis-sdk/LICENSE b/external/antithesis-sdk/LICENSE new file mode 100644 index 00000000000..90f1712ed1a --- /dev/null +++ b/external/antithesis-sdk/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Antithesis + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/external/antithesis-sdk/README.md b/external/antithesis-sdk/README.md new file mode 100644 index 00000000000..ce512d7c6fd --- /dev/null +++ b/external/antithesis-sdk/README.md @@ -0,0 +1,8 @@ +# Antithesis C++ SDK + +This library provides methods for C++ programs to configure the [Antithesis](https://antithesis.com) platform. It contains three kinds of functionality: +* Assertion macros that allow you to define test properties about your software or workload. +* Randomness functions for requesting both structured and unstructured randomness from the Antithesis platform. +* Lifecycle functions that inform the Antithesis environment that particular test phases or milestones have been reached. + +For general usage guidance see the [Antithesis C++ SDK Documentation](https://antithesis.com/docs/using_antithesis/sdk/cpp/overview.html) diff --git a/external/antithesis-sdk/antithesis_instrumentation.h b/external/antithesis-sdk/antithesis_instrumentation.h new file mode 100644 index 00000000000..a2e88dbef5d --- /dev/null +++ b/external/antithesis-sdk/antithesis_instrumentation.h @@ -0,0 +1,113 @@ +#pragma once + +/* +This header file enables code coverage instrumentation. It is distributed with the Antithesis C++ SDK. + +This header file can be used in both C and C++ programs. (The rest of the SDK works only for C++ programs.) + +You should include it in a single .cpp or .c file. + +The instructions (such as required compiler flags) and usage guidance are found at https://antithesis.com/docs/using_antithesis/sdk/cpp/overview.html. +*/ + +#include +#include +#include +#include +#include +#ifndef __cplusplus +#include +#include +#endif + +// If the libvoidstar(determ) library is present, +// pass thru trace_pc_guard related callbacks to it +typedef void (*trace_pc_guard_init_fn)(uint32_t *start, uint32_t *stop); +typedef void (*trace_pc_guard_fn)(uint32_t *guard, uint64_t edge); + +static trace_pc_guard_init_fn trace_pc_guard_init = NULL; +static trace_pc_guard_fn trace_pc_guard = NULL; +static bool did_check_libvoidstar = false; +static bool has_libvoidstar = false; + +static __attribute__((no_sanitize("coverage"))) void debug_message_out(const char *msg) { + (void)printf("%s\n", msg); + return; +} + +extern +#ifdef __cplusplus + "C" +#endif +__attribute__((no_sanitize("coverage"))) void antithesis_load_libvoidstar() { +#ifdef __cplusplus + constexpr +#endif + const char* LIB_PATH = "/usr/lib/libvoidstar.so"; + + if (did_check_libvoidstar) { + return; + } + debug_message_out("TRYING TO LOAD libvoidstar"); + did_check_libvoidstar = true; + void* shared_lib = dlopen(LIB_PATH, RTLD_NOW); + if (!shared_lib) { + debug_message_out("Can not load the Antithesis native library"); + return; + } + + void* trace_pc_guard_init_sym = dlsym(shared_lib, "__sanitizer_cov_trace_pc_guard_init"); + if (!trace_pc_guard_init_sym) { + debug_message_out("Can not forward calls to libvoidstar for __sanitizer_cov_trace_pc_guard_init"); + return; + } + + void* trace_pc_guard_sym = dlsym(shared_lib, "__sanitizer_cov_trace_pc_guard_internal"); + if (!trace_pc_guard_sym) { + debug_message_out("Can not forward calls to libvoidstar for __sanitizer_cov_trace_pc_guard"); + return; + } + + trace_pc_guard_init = (trace_pc_guard_init_fn)(trace_pc_guard_init_sym); + trace_pc_guard = (trace_pc_guard_fn)(trace_pc_guard_sym); + has_libvoidstar = true; + debug_message_out("LOADED libvoidstar"); +} + +// The following symbols are indeed reserved identifiers, since we're implementing functions defined +// in the compiler runtime. Not clear how to get Clang on board with that besides narrowly suppressing +// the warning in this case. The sample code on the CoverageSanitizer documentation page fails this +// warning! +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreserved-identifier" +extern +#ifdef __cplusplus + "C" +#endif +void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { + debug_message_out("SDK forwarding to libvoidstar for __sanitizer_cov_trace_pc_guard_init()"); + if (!did_check_libvoidstar) { + antithesis_load_libvoidstar(); + } + if (has_libvoidstar) { + trace_pc_guard_init(start, stop); + } + return; +} + +extern +#ifdef __cplusplus + "C" +#endif +void __sanitizer_cov_trace_pc_guard( uint32_t *guard ) { + if (has_libvoidstar) { + uint64_t edge = (uint64_t)(__builtin_return_address(0)); + trace_pc_guard(guard, edge); + } else { + if (guard) { + *guard = 0; + } + } + return; +} +#pragma clang diagnostic pop diff --git a/external/antithesis-sdk/antithesis_sdk.h b/external/antithesis-sdk/antithesis_sdk.h new file mode 100644 index 00000000000..f6ed8e52d33 --- /dev/null +++ b/external/antithesis-sdk/antithesis_sdk.h @@ -0,0 +1,1093 @@ +#pragma once + +// This header file contains the Antithesis C++ SDK, which enables C++ applications to integrate with the [Antithesis platform]. +// +// Documentation for the SDK is found at https://antithesis.com/docs/using_antithesis/sdk/cpp/overview.html. + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace antithesis { + inline const char* SDK_VERSION = "0.4.0"; + inline const char* PROTOCOL_VERSION = "1.1.0"; + + struct LocalRandom { + std::random_device device; + std::mt19937_64 gen; + std::uniform_int_distribution distribution; + + LocalRandom() : device(), gen(device()), distribution() {} + + uint64_t random() { +#ifdef ANTITHESIS_RANDOM_OVERRIDE + return ANTITHESIS_RANDOM_OVERRIDE(); +#else + return distribution(gen); +#endif + } + }; + + struct JSON; struct JSONArray; + typedef std::variant JSONValue; + + struct JSONArray : std::vector { + using std::vector::vector; + + template::value, bool>::type = true> + JSONArray(std::vector vals) : std::vector(vals.begin(), vals.end()) {} + }; + + struct JSON : std::map { + JSON() : std::map() {} + JSON( std::initializer_list> args) : std::map(args) {} + + JSON( std::initializer_list> args, std::vector> more_args ) : std::map(args) { + for (auto& pair : more_args) { + (*this)[pair.first] = pair.second; + } + } + }; + + // Declarations that we expose + uint64_t get_random(); +} + +#if defined(NO_ANTITHESIS_SDK) || __cplusplus < 202000L || (defined(__clang__) && __clang_major__ < 16) + +#if __cplusplus < 202000L + #error "The Antithesis C++ API requires C++20 or higher" +#endif +#if defined(__clang__) && __clang_major__ < 16 + #error "The Antithesis C++ API requires clang version 16 or higher" +#endif + +#define ALWAYS(cond, message, ...) +#define ALWAYS_OR_UNREACHABLE(cond, message, ...) +#define SOMETIMES(cond, message, ...) +#define REACHABLE(message, ...) +#define UNREACHABLE(message, ...) +#define ALWAYS_GREATER_THAN(val, threshold, message, ...) +#define ALWAYS_GREATER_THAN_OR_EQUAL_TO(val, threshold, message, ...) +#define SOMETIMES_GREATER_THAN(val, threshold, message, ...) +#define SOMETIMES_GREATER_THAN_OR_EQUAL_TO(val, threshold, message, ...) +#define ALWAYS_LESS_THAN(val, threshold, message, ...) +#define ALWAYS_LESS_THAN_OR_EQUAL_TO(val, threshold, message, ...) +#define SOMETIMES_LESS_THAN(val, threshold, message, ...) +#define SOMETIMES_LESS_THAN_OR_EQUAL_TO(val, threshold, message, ...) +#define ALWAYS_SOME(pairs, message, ...) +#define SOMETIMES_ALL(pairs, message, ...) + +namespace antithesis { + inline uint64_t get_random() { + static LocalRandom random_gen; + return random_gen.random(); + } + + inline void setup_complete(const JSON& details) { + } + + inline void send_event(const char* name, const JSON& details) { + } +} + +#else + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace antithesis { + constexpr const char* const ERROR_LOG_LINE_PREFIX = "[* antithesis-sdk-cpp *]"; + constexpr const char* LIB_PATH = "/usr/lib/libvoidstar.so"; + constexpr const char* LOCAL_OUTPUT_ENVIRONMENT_VARIABLE = "ANTITHESIS_SDK_LOCAL_OUTPUT"; + + static std::ostream& operator<<(std::ostream& out, const JSON& details); + + struct LibHandler { + virtual ~LibHandler() = default; + virtual void output(const char* message) const = 0; + virtual uint64_t random() = 0; + + void output(const JSON& json) const { + std::ostringstream out; + out << json; + output(out.str().c_str()); + } + }; + + struct AntithesisHandler : LibHandler { + void output(const char* message) const override { + if (message != nullptr) { + fuzz_json_data(message, strlen(message)); + fuzz_flush(); + } + } + + uint64_t random() override { + return fuzz_get_random(); + } + + static std::unique_ptr create() { + void* shared_lib = dlopen(LIB_PATH, RTLD_NOW); + if (!shared_lib) { + error("Can not load the Antithesis native library"); + return nullptr; + } + + void* fuzz_json_data = dlsym(shared_lib, "fuzz_json_data"); + if (!fuzz_json_data) { + error("Can not access symbol fuzz_json_data"); + return nullptr; + } + + void* fuzz_flush = dlsym(shared_lib, "fuzz_flush"); + if (!fuzz_flush) { + error("Can not access symbol fuzz_flush"); + return nullptr; + } + + void* fuzz_get_random = dlsym(shared_lib, "fuzz_get_random"); + if (!fuzz_get_random) { + error("Can not access symbol fuzz_get_random"); + return nullptr; + } + + return std::unique_ptr(new AntithesisHandler( + reinterpret_cast(fuzz_json_data), + reinterpret_cast(fuzz_flush), + reinterpret_cast(fuzz_get_random))); + } + + private: + typedef void (*fuzz_json_data_t)( const char* message, size_t length ); + typedef void (*fuzz_flush_t)(); + typedef uint64_t (*fuzz_get_random_t)(); + + + fuzz_json_data_t fuzz_json_data; + fuzz_flush_t fuzz_flush; + fuzz_get_random_t fuzz_get_random; + + AntithesisHandler(fuzz_json_data_t fuzz_json_data, fuzz_flush_t fuzz_flush, fuzz_get_random_t fuzz_get_random) : + fuzz_json_data(fuzz_json_data), fuzz_flush(fuzz_flush), fuzz_get_random(fuzz_get_random) {} + + static void error(const char* message) { + fprintf(stderr, "%s %s: %s\n", ERROR_LOG_LINE_PREFIX, message, dlerror()); + } + }; + + struct LocalHandler : LibHandler{ + ~LocalHandler() override { + if (file != nullptr) { + fclose(file); + } + } + + void output(const char* message) const override { + if (file != nullptr && message != nullptr) { + fprintf(file, "%s\n", message); + } + } + + uint64_t random() override { + return random_gen.random(); + } + + static std::unique_ptr create() { + return std::unique_ptr(new LocalHandler(create_internal())); + } + private: + FILE* file; + LocalRandom random_gen; + + LocalHandler(FILE* file): file(file), random_gen() { + } + + // If `localOutputEnvVar` is set to a non-empty path, attempt to open that path and truncate the file + // to serve as the log file of the local handler. + // Otherwise, we don't have a log file, and logging is a no-op in the local handler. + static FILE* create_internal() { + const char* path = std::getenv(LOCAL_OUTPUT_ENVIRONMENT_VARIABLE); + if (!path || !path[0]) { + return nullptr; + } + + // Open the file for writing (create if needed and possible) and truncate it + FILE* file = fopen(path, "w"); + if (file == nullptr) { + fprintf(stderr, "%s Failed to open path %s: %s\n", ERROR_LOG_LINE_PREFIX, path, strerror(errno)); + return nullptr; + } + int ret = fchmod(fileno(file), 0644); + if (ret != 0) { + fprintf(stderr, "%s Failed to set permissions for path %s: %s\n", ERROR_LOG_LINE_PREFIX, path, strerror(errno)); + fclose(file); + return nullptr; + } + + return file; + } + }; + + static std::unique_ptr init() { + struct stat stat_buf; + if (stat(LIB_PATH, &stat_buf) == 0) { + std::unique_ptr tmp = AntithesisHandler::create(); + if (!tmp) { + fprintf(stderr, "%s Failed to create handler for Antithesis library\n", ERROR_LOG_LINE_PREFIX); + exit(-1); + } + return tmp; + } else { + return LocalHandler::create(); + } + } + + struct AssertionState { + uint8_t false_not_seen : 1; + uint8_t true_not_seen : 1; + uint8_t rest : 6; + + AssertionState() : false_not_seen(true), true_not_seen(true), rest(0) {} + }; + + template + inline constexpr bool always_false_v = false; + + static std::ostream& operator<<(std::ostream& out, const JSONValue& json) { + std::visit([&](auto&& arg) + { + using T = std::decay_t; + if constexpr (std::is_same_v) { + out << std::quoted(arg); + } else if constexpr (std::is_same_v) { + out << (arg ? "true" : "false"); + } else if constexpr (std::is_same_v) { + char tmp[2] = {arg, '\0'}; + out << std::quoted(tmp); + } else if constexpr (std::is_same_v) { + out << arg; + } else if constexpr (std::is_same_v) { + out << arg; + } else if constexpr (std::is_same_v) { + out << arg; + } else if constexpr (std::is_same_v) { + out << arg; + } else if constexpr (std::is_same_v) { + out << std::quoted(arg); + } else if constexpr (std::is_same_v) { + out << "null"; + } else if constexpr (std::is_same_v) { + out << arg; + } else if constexpr (std::is_same_v) { + out << '['; + bool first = true; + for (auto &item : arg) { + if (!first) { + out << ','; + } + first = false; + out << item; + } + out << ']'; + } else { + static_assert(always_false_v, "non-exhaustive JSONValue visitor!"); + } + }, json); + + return out; + } + + static std::ostream& operator<<(std::ostream& out, const JSON& details) { + out << '{'; + + bool first = true; + for (auto [key, value] : details) { + if (!first) { + out << ','; + } + out << std::quoted(key) << ':' << value; + first = false; + } + + out << '}'; + return out; + } + + enum AssertionType { + ALWAYS_ASSERTION, + ALWAYS_OR_UNREACHABLE_ASSERTION, + SOMETIMES_ASSERTION, + REACHABLE_ASSERTION, + UNREACHABLE_ASSERTION, + }; + + inline constexpr bool get_must_hit(AssertionType type) { + switch (type) { + case ALWAYS_ASSERTION: + case SOMETIMES_ASSERTION: + case REACHABLE_ASSERTION: + return true; + case ALWAYS_OR_UNREACHABLE_ASSERTION: + case UNREACHABLE_ASSERTION: + return false; + } + } + + inline constexpr const char* get_assert_type_string(AssertionType type) { + switch (type) { + case ALWAYS_ASSERTION: + case ALWAYS_OR_UNREACHABLE_ASSERTION: + return "always"; + case SOMETIMES_ASSERTION: + return "sometimes"; + case REACHABLE_ASSERTION: + case UNREACHABLE_ASSERTION: + return "reachability"; + } + } + + inline constexpr const char* get_display_type_string(AssertionType type) { + switch (type) { + case ALWAYS_ASSERTION: return "Always"; + case ALWAYS_OR_UNREACHABLE_ASSERTION: return "AlwaysOrUnreachable"; + case SOMETIMES_ASSERTION: return "Sometimes"; + case REACHABLE_ASSERTION: return "Reachable"; + case UNREACHABLE_ASSERTION: return "Unreachable"; + } + } + + struct LocationInfo { + const char* class_name; + const char* function_name; + const char* file_name; + const int line; + const int column; + + JSON to_json() const { + return JSON{ + {"class", class_name}, + {"function", function_name}, + {"file", file_name}, + {"begin_line", line}, + {"begin_column", column}, + }; + } + }; + + inline std::string make_key([[maybe_unused]] const char* message, const LocationInfo& location_info) { + return message; + } + + inline LibHandler& get_lib_handler() { + static LibHandler* lib_handler = nullptr; + if (lib_handler == nullptr) { + lib_handler = init().release(); // Leak on exit, rather than exit-time-destructor + + JSON language_block{ + {"name", "C++"}, + {"version", __VERSION__} + }; + + JSON version_message{ + {"antithesis_sdk", JSON{ + {"language", language_block}, + {"sdk_version", SDK_VERSION}, + {"protocol_version", PROTOCOL_VERSION} + } + }}; + lib_handler->output(version_message); + } + + return *lib_handler; + } + + inline void assert_impl(bool cond, const char* message, const JSON& details, const LocationInfo& location_info, + bool hit, bool must_hit, const char* assert_type, const char* display_type, const char* id) { + JSON assertion{ + {"antithesis_assert", JSON{ + {"hit", hit}, + {"must_hit", must_hit}, + {"assert_type", assert_type}, + {"display_type", display_type}, + {"message", message}, + {"condition", cond}, + {"id", id}, + {"location", location_info.to_json()}, + {"details", details}, + }} + }; + get_lib_handler().output(assertion); + } + + inline void assert_raw(bool cond, const char* message, const JSON& details, + const char* class_name, const char* function_name, const char* file_name, const int line, const int column, + bool hit, bool must_hit, const char* assert_type, const char* display_type, const char* id) { + LocationInfo location_info{ class_name, function_name, file_name, line, column }; + assert_impl(cond, message, details, location_info, hit, must_hit, assert_type, display_type, id); + } + + typedef std::set CatalogEntryTracker; + + inline CatalogEntryTracker& get_catalog_entry_tracker() { + static CatalogEntryTracker catalog_entry_tracker; + return catalog_entry_tracker; + } + + struct Assertion { + AssertionState state; + AssertionType type; + const char* message; + LocationInfo location; + + Assertion(const char* message, AssertionType type, LocationInfo&& location) : + state(), type(type), message(message), location(std::move(location)) { + this->add_to_catalog(); + } + + void add_to_catalog() const { + std::string id = make_key(message, location); + CatalogEntryTracker& tracker = get_catalog_entry_tracker(); + if (!tracker.contains(id)) { + tracker.insert(id); + const bool condition = (type == REACHABLE_ASSERTION ? true : false); + const bool hit = false; + const char* assert_type = get_assert_type_string(type); + const bool must_hit = get_must_hit(type); + const char* display_type = get_display_type_string(type); + assert_impl(condition, message, {}, location, hit, must_hit, assert_type, display_type, id.c_str()); + } + } + + [[clang::always_inline]] inline void check_assertion(bool cond, const JSON& details) { + #if defined(NO_ANTITHESIS_SDK) + #error "Antithesis SDK has been disabled" + #endif + if (__builtin_expect(state.false_not_seen || state.true_not_seen, false)) { + check_assertion_internal(cond, details); + } + } + + private: + void check_assertion_internal(bool cond, const JSON& details) { + bool emit = false; + if (!cond && state.false_not_seen) { + emit = true; + state.false_not_seen = false; // TODO: is the race OK? + } + + if (cond && state.true_not_seen) { + emit = true; + state.true_not_seen = false; // TODO: is the race OK? + } + + if (emit) { + const bool hit = true; + const char* assert_type = get_assert_type_string(type); + const bool must_hit = get_must_hit(type); + const char* display_type = get_display_type_string(type); + std::string id = make_key(message, location); + assert_impl(cond, message, details, location, hit, must_hit, assert_type, display_type, id.c_str()); + } + } + }; + + inline uint64_t get_random() { + return get_lib_handler().random(); + } + + inline void setup_complete(const JSON& details) { + JSON json{ + { "antithesis_setup", JSON{ + {"status", "complete"}, + {"details", details} + }} + }; + get_lib_handler().output(json); + } + + inline void send_event(const char* name, const JSON& details) { + JSON json = { { name, details } }; + get_lib_handler().output(json); + } + + enum GuidepostType { + GUIDEPOST_MAXIMIZE, + GUIDEPOST_MINIMIZE, + GUIDEPOST_EXPLORE, + GUIDEPOST_ALL, + GUIDEPOST_NONE + }; + + inline constexpr const char* get_guidance_type_string(GuidepostType type) { + switch (type) { + case GUIDEPOST_MAXIMIZE: + case GUIDEPOST_MINIMIZE: + return "numeric"; + case GUIDEPOST_ALL: + case GUIDEPOST_NONE: + return "boolean"; + case GUIDEPOST_EXPLORE: + return "json"; + } + } + + inline constexpr bool does_guidance_maximize(GuidepostType type) { + switch (type) { + case GUIDEPOST_MAXIMIZE: + case GUIDEPOST_ALL: + return true; + case GUIDEPOST_EXPLORE: + case GUIDEPOST_MINIMIZE: + case GUIDEPOST_NONE: + return false; + } + } + + template > + struct NumericGuidepost { + const char* message; + LocationInfo location; + GuidepostType type; + // an approximation of (left - right) / 2; contains an absolute value and a sign bit + std::pair extreme_half_gap; + + NumericGuidepost(const char* message, LocationInfo&& location, GuidepostType type) : + message(message), location(std::move(location)), type(type) { + this->add_to_catalog(); + if (type == GUIDEPOST_MAXIMIZE) { + extreme_half_gap = { std::numeric_limits::max(), false }; + } else { + extreme_half_gap = { std::numeric_limits::max(), true }; + } + } + + inline void add_to_catalog() { + std::string id = make_key(message, location); + JSON catalog{ + {"antithesis_guidance", JSON{ + {"guidance_type", get_guidance_type_string(type)}, + {"message", message}, + {"id", id}, + {"location", location.to_json()}, + {"maximize", does_guidance_maximize(type)}, + {"hit", false} + }} + }; + get_lib_handler().output(catalog); + } + + std::pair compute_half_gap(NumericValue left, NumericValue right) { + // An extremely baroque way to compute (left - right) / 2, rounded toward 0, without overflowing or underflowing + if (std::is_integral_v) { + // If both numbers are odd then the gap doesn't change if we subtract 1 from both sides + // Also subtracting 1 from both sides won't underflow + if (left % 2 == 1 && right % 2 == 1) + return compute_half_gap( left - 1, right - 1); + // If one number is odd then we subtract 1 from the larger number + // This rounds the computation toward 0 but again won't underflow + if (left % 2 == 1 || right % 2 == 1) { + if (left > right) { + return compute_half_gap( left - 1, right ); + } else { + return compute_half_gap( left, right - 1 ); + } + } + // At this point both numbers are even, so the midpoint calculation is exact + NumericValue half_left = left / 2; + NumericValue half_right = right / 2; + NumericValue midpoint = half_left + half_right; + // This won't overflow or underflow because we're subtracting the midpoint + // We compute a positive value and a sign so that we don't have to do weird things with unsigned types + if (left > right) { + return { midpoint - right, true }; + } else { + return { right - midpoint, false }; + } + } else { + // If it's floating point we don't need to worry about overflowing, just do the arithmetic + return { left > right ? (left - right) / 2 : (right - left) / 2, left > right }; + } + } + + bool should_send_value(std::pair half_gap) { + if (this->type == GUIDEPOST_MAXIMIZE) { + if (half_gap.second && !extreme_half_gap.second) { + // we're positive and the extreme value isn't; always send back + return true; + } else if (!half_gap.second && extreme_half_gap.second) { + // we're negative and the extreme value is positive; never send back + return false; + } else if (half_gap.second && extreme_half_gap.second) { + // both positive; send back if our absolute value is at least as large + return half_gap.first >= extreme_half_gap.first; + } else { + // both negative; send back if our absolute value is at least as small + return half_gap.first <= extreme_half_gap.first; + } + } else { + if (half_gap.second && !extreme_half_gap.second) { + // we're positive and the extreme value isn't; never send back + return false; + } else if (!half_gap.second && extreme_half_gap.second) { + // we're negative and the extreme value is positive; always send back + return true; + } else if (half_gap.second && extreme_half_gap.second) { + // both positive; send back if our absolute value is at least as small + return half_gap.first <= extreme_half_gap.first; + } else { + // both negative; send back if our absolute value is at least as large + return half_gap.first >= extreme_half_gap.first; + } + } + } + + [[clang::always_inline]] inline void send_guidance(Value value) { + std::pair half_gap = compute_half_gap(value.first, value.second); + if (should_send_value(half_gap)) { + extreme_half_gap = half_gap; + std::string id = make_key(this->message, this->location); + JSON guidance{ + {"antithesis_guidance", JSON{ + {"guidance_type", get_guidance_type_string(this->type)}, + {"message", this->message}, + {"id", id}, + {"location", this->location.to_json()}, + {"maximize", does_guidance_maximize(this->type)}, + {"guidance_data", JSON{ + { "left", value.first }, + { "right", value.second } }}, + {"hit", true} + }} + }; + get_lib_handler().output(guidance); + } + } + }; + + template + struct BooleanGuidepost { + const char* message; + LocationInfo location; + GuidepostType type; + + BooleanGuidepost(const char* message, LocationInfo&& location, GuidepostType type) : + message(message), location(std::move(location)), type(type) { + this->add_to_catalog(); + } + + inline void add_to_catalog() { + std::string id = make_key(message, location); + JSON catalog{ + {"antithesis_guidance", JSON{ + {"guidance_type", get_guidance_type_string(type)}, + {"message", message}, + {"id", id}, + {"location", location.to_json()}, + {"maximize", does_guidance_maximize(type)}, + {"hit", false} + }} + }; + get_lib_handler().output(catalog); + } + + inline virtual void send_guidance(GuidanceType data) { + std::string id = make_key(this->message, this->location); + JSON guidance{ + {"antithesis_guidance", JSON{ + {"guidance_type", get_guidance_type_string(this->type)}, + {"message", this->message}, + {"id", id}, + {"location", location.to_json()}, + {"maximize", does_guidance_maximize(this->type)}, + {"guidance_data", data}, + {"hit", true} + }} + }; + get_lib_handler().output(guidance); + } + }; +} + +namespace { + template + struct fixed_string { + std::array contents; + constexpr fixed_string() { + for(unsigned int i=0; i from_c_str( const char* s ) { + fixed_string it; + for(unsigned int i=0; i + fixed_string( const char (&arr)[N] ) -> fixed_string; + + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" + static constexpr size_t string_length( const char * s ) { + for(int l = 0; ; l++) + if (!s[l]) + return l; + } + #pragma clang diagnostic pop + + template + struct CatalogEntry { + [[clang::always_inline]] static inline antithesis::Assertion create() { + antithesis::LocationInfo location{ "", function_name.c_str(), file_name.c_str(), line, column }; + return antithesis::Assertion(message.c_str(), type, std::move(location)); + } + + static inline antithesis::Assertion assertion = create(); + }; + + template + struct BooleanGuidanceCatalogEntry { + [[clang::always_inline]] static inline antithesis::BooleanGuidepost create() { + antithesis::LocationInfo location{ "", function_name.c_str(), file_name.c_str(), line, column }; + switch (type) { + case antithesis::GUIDEPOST_ALL: + case antithesis::GUIDEPOST_NONE: + return antithesis::BooleanGuidepost(message.c_str(), std::move(location), type); + default: + throw std::runtime_error("Can't create boolean guidepost with non-boolean type"); + } + } + + static inline antithesis::BooleanGuidepost guidepost = create(); + }; + + template + struct NumericGuidanceCatalogEntry { + [[clang::always_inline]] static inline antithesis::NumericGuidepost create() { + antithesis::LocationInfo location{ "", function_name.c_str(), file_name.c_str(), line, column }; + switch (type) { + case antithesis::GUIDEPOST_MAXIMIZE: + case antithesis::GUIDEPOST_MINIMIZE: + return antithesis::NumericGuidepost(message.c_str(), std::move(location), type); + default: + throw std::runtime_error("Can't create numeric guidepost with non-numeric type"); + } + } + + static inline antithesis::NumericGuidepost guidepost = create(); + }; +} + +#define FIXED_STRING_FROM_C_STR(s) (fixed_string::from_c_str(s)) + +#define _NL_1(foo) { #foo, foo } +#define _NL_2(foo, ...) { #foo, foo }, _NL_1(__VA_ARGS__) +#define _NL_3(foo, ...) { #foo, foo }, _NL_2(__VA_ARGS__) +#define _NL_4(foo, ...) { #foo, foo }, _NL_3(__VA_ARGS__) +#define _NL_5(foo, ...) { #foo, foo }, _NL_4(__VA_ARGS__) +#define _NL_6(foo, ...) { #foo, foo }, _NL_5(__VA_ARGS__) +#define _NL_7(foo, ...) { #foo, foo }, _NL_6(__VA_ARGS__) +#define _NL_8(foo, ...) { #foo, foo }, _NL_7(__VA_ARGS__) +#define _NL_9(foo, ...) { #foo, foo }, _NL_8(__VA_ARGS__) +#define _NL_10(foo, ...) { #foo, foo }, _NL_9(__VA_ARGS__) + +#define _ELEVENTH_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N + +#define _GET_NL(...) \ + _ELEVENTH_ARG(__VA_ARGS__, _NL_10, _NL_9, _NL_8, _NL_7, _NL_6, _NL_5, _NL_4, _NL_3, _NL_2, _NL_1) + +#define NAMED_LIST(...) { _GET_NL(__VA_ARGS__)(__VA_ARGS__) } + +#define ANTITHESIS_ASSERT_RAW(type, cond, message, ...) ( \ + CatalogEntry< \ + type, \ + fixed_string(message), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().file_name()), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().function_name()), \ + std::source_location::current().line(), \ + std::source_location::current().column() \ + >::assertion.check_assertion(cond, (antithesis::JSON(__VA_ARGS__)) ) ) + +#define ALWAYS(cond, message, ...) ANTITHESIS_ASSERT_RAW(antithesis::ALWAYS_ASSERTION, cond, message, __VA_ARGS__) +#define ALWAYS_OR_UNREACHABLE(cond, message, ...) ANTITHESIS_ASSERT_RAW(antithesis::ALWAYS_OR_UNREACHABLE_ASSERTION, cond, message, __VA_ARGS__) +#define SOMETIMES(cond, message, ...) ANTITHESIS_ASSERT_RAW(antithesis::SOMETIMES_ASSERTION, cond, message, __VA_ARGS__) +#define REACHABLE(message, ...) ANTITHESIS_ASSERT_RAW(antithesis::REACHABLE_ASSERTION, true, message, __VA_ARGS__) +#define UNREACHABLE(message, ...) ANTITHESIS_ASSERT_RAW(antithesis::UNREACHABLE_ASSERTION, false, message, __VA_ARGS__) + +#define ALWAYS_GREATER_THAN(left, right, message, ...) \ +do { \ + static_assert(std::is_same_v, "Values compared in ALWAYS_GREATER_THAN must be of same type"); \ + CatalogEntry< \ + antithesis::ALWAYS_ASSERTION, \ + fixed_string(message), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().file_name()), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().function_name()), \ + std::source_location::current().line(), \ + std::source_location::current().column() \ + >::assertion.check_assertion(left > right, (antithesis::JSON(__VA_ARGS__, {{ "left", left }, { "right", right }})) ); \ + NumericGuidanceCatalogEntry< \ + decltype(left), \ + antithesis::GUIDEPOST_MINIMIZE, \ + fixed_string(message), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().file_name()), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().function_name()), \ + std::source_location::current().line(), \ + std::source_location::current().column() \ + >::guidepost.send_guidance({ left, right }); \ +} while (0) + +#define ALWAYS_GREATER_THAN_OR_EQUAL_TO(left, right, message, ...) \ +do { \ + static_assert(std::is_same_v, "Values compared in ALWAYS_GREATER_THAN_OR_EQUAL_TO must be of same type"); \ + CatalogEntry< \ + antithesis::ALWAYS_ASSERTION, \ + fixed_string(message), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().file_name()), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().function_name()), \ + std::source_location::current().line(), \ + std::source_location::current().column() \ + >::assertion.check_assertion(left >= right, (antithesis::JSON(__VA_ARGS__, {{ "left", left }, { "right", right }})) ); \ + NumericGuidanceCatalogEntry< \ + decltype(left), \ + antithesis::GUIDEPOST_MINIMIZE, \ + fixed_string(message), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().file_name()), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().function_name()), \ + std::source_location::current().line(), \ + std::source_location::current().column() \ + >::guidepost.send_guidance({ left, right }); \ +} while (0) + +#define SOMETIMES_GREATER_THAN(left, right, message, ...) \ +do { \ + static_assert(std::is_same_v, "Values compared in SOMETIMES_GREATER_THAN must be of same type"); \ + CatalogEntry< \ + antithesis::SOMETIMES_ASSERTION, \ + fixed_string(message), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().file_name()), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().function_name()), \ + std::source_location::current().line(), \ + std::source_location::current().column() \ + >::assertion.check_assertion(left > right, (antithesis::JSON(__VA_ARGS__, {{ "left", left }, { "right", right }})) ); \ + NumericGuidanceCatalogEntry< \ + decltype(left), \ + antithesis::GUIDEPOST_MAXIMIZE, \ + fixed_string(message), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().file_name()), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().function_name()), \ + std::source_location::current().line(), \ + std::source_location::current().column() \ + >::guidepost.send_guidance({ left, right }); \ +} while (0) + +#define SOMETIMES_GREATER_THAN_OR_EQUAL_TO(left, right, message, ...) \ +do { \ + static_assert(std::is_same_v, "Values compared in SOMETIMES_GREATER_THAN_OR_EQUAL_TO must be of same type"); \ + CatalogEntry< \ + antithesis::SOMETIMES_ASSERTION, \ + fixed_string(message), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().file_name()), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().function_name()), \ + std::source_location::current().line(), \ + std::source_location::current().column() \ + >::assertion.check_assertion(left >= right, (antithesis::JSON(__VA_ARGS__, {{ "left", left }, { "right", right }})) ); \ + NumericGuidanceCatalogEntry< \ + decltype(left), \ + antithesis::GUIDEPOST_MAXIMIZE, \ + fixed_string(message), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().file_name()), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().function_name()), \ + std::source_location::current().line(), \ + std::source_location::current().column() \ + >::guidepost.send_guidance({ left, right }); \ +} while (0) + +#define ALWAYS_LESS_THAN(left, right, message, ...) \ +do { \ + static_assert(std::is_same_v, "Values compared in ALWAYS_LESS_THAN must be of same type"); \ + CatalogEntry< \ + antithesis::ALWAYS_ASSERTION, \ + fixed_string(message), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().file_name()), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().function_name()), \ + std::source_location::current().line(), \ + std::source_location::current().column() \ + >::assertion.check_assertion(left < right, (antithesis::JSON(__VA_ARGS__, {{ "left", left }, { "right", right }})) ); \ + NumericGuidanceCatalogEntry< \ + decltype(left), \ + antithesis::GUIDEPOST_MAXIMIZE, \ + fixed_string(message), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().file_name()), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().function_name()), \ + std::source_location::current().line(), \ + std::source_location::current().column() \ + >::guidepost.send_guidance({ left, right }); \ +} while (0) + +#define ALWAYS_LESS_THAN_OR_EQUAL_TO(left, right, message, ...) \ +do { \ + static_assert(std::is_same_v, "Values compared in ALWAYS_LESS_THAN_OR_EQUAL_TO must be of same type"); \ + CatalogEntry< \ + antithesis::ALWAYS_ASSERTION, \ + fixed_string(message), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().file_name()), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().function_name()), \ + std::source_location::current().line(), \ + std::source_location::current().column() \ + >::assertion.check_assertion(left <= right, (antithesis::JSON(__VA_ARGS__, {{ "left", left }, { "right", right }})) ); \ + NumericGuidanceCatalogEntry< \ + decltype(left), \ + antithesis::GUIDEPOST_MAXIMIZE, \ + fixed_string(message), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().file_name()), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().function_name()), \ + std::source_location::current().line(), \ + std::source_location::current().column() \ + >::guidepost.send_guidance({ left, right }); \ +} while (0) + +#define SOMETIMES_LESS_THAN(left, right, message, ...) \ +do { \ + static_assert(std::is_same_v, "Values compared in SOMETIMES_LESS_THAN must be of same type"); \ + CatalogEntry< \ + antithesis::SOMETIMES_ASSERTION, \ + fixed_string(message), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().file_name()), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().function_name()), \ + std::source_location::current().line(), \ + std::source_location::current().column() \ + >::assertion.check_assertion(left < right, (antithesis::JSON(__VA_ARGS__, {{ "left", left }, { "right", right }})) ); \ + NumericGuidanceCatalogEntry< \ + decltype(left), \ + antithesis::GUIDEPOST_MINIMIZE, \ + fixed_string(message), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().file_name()), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().function_name()), \ + std::source_location::current().line(), \ + std::source_location::current().column() \ + >::guidepost.send_guidance({ left, right }); \ +} while (0) + +#define SOMETIMES_LESS_THAN_OR_EQUAL_TO(left, right, message, ...) \ +do { \ + static_assert(std::is_same_v, "Values compared in SOMETIMES_LESS_THAN_OR_EQUAL_TO must be of same type"); \ + CatalogEntry< \ + antithesis::SOMETIMES_ASSERTION, \ + fixed_string(message), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().file_name()), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().function_name()), \ + std::source_location::current().line(), \ + std::source_location::current().column() \ + >::assertion.check_assertion(left <= right, (antithesis::JSON(__VA_ARGS__, {{ "left", left }, { "right", right }})) ); \ + NumericGuidanceCatalogEntry< \ + decltype(left), \ + antithesis::GUIDEPOST_MINIMIZE, \ + fixed_string(message), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().file_name()), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().function_name()), \ + std::source_location::current().line(), \ + std::source_location::current().column() \ + >::guidepost.send_guidance({ left, right }); \ +} while (0) + +#define ALWAYS_SOME(pairs, message, ...) \ +do { \ + bool disjunction = false; \ + for (std::pair pair : pairs) { \ + if (pair.second) { \ + disjunction = true; \ + break; \ + } \ + } \ + CatalogEntry< \ + antithesis::ALWAYS_ASSERTION, \ + fixed_string(message), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().file_name()), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().function_name()), \ + std::source_location::current().line(), \ + std::source_location::current().column() \ + >::assertion.check_assertion(disjunction, (antithesis::JSON(__VA_ARGS__, pairs)) ); \ + antithesis::json json_pairs = antithesis::json(pairs); \ + BooleanGuidanceCatalogEntry< \ + decltype(json_pairs), \ + antithesis::GUIDEPOST_NONE, \ + fixed_string(message), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().file_name()), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().function_name()), \ + std::source_location::current().line(), \ + std::source_location::current().column() \ + >::guidepost.send_guidance(json_pairs); \ +} while (0) + +#define SOMETIMES_ALL(pairs, message, ...) \ +do { \ + bool conjunction = true; \ + for (std::pair pair : pairs) { \ + if (!pair.second) { \ + conjunction = false; \ + break; \ + } \ + } \ + CatalogEntry< \ + antithesis::SOMETIMES_ASSERTION, \ + fixed_string(message), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().file_name()), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().function_name()), \ + std::source_location::current().line(), \ + std::source_location::current().column() \ + >::assertion.check_assertion(conjunction, (antithesis::JSON(__VA_ARGS__, pairs)) ); \ + antithesis::json json_pairs = antithesis::json(pairs); \ + BooleanGuidanceCatalogEntry< \ + decltype(json_pairs), \ + antithesis::GUIDEPOST_ALL, \ + fixed_string(message), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().file_name()), \ + FIXED_STRING_FROM_C_STR(std::source_location::current().function_name()), \ + std::source_location::current().line(), \ + std::source_location::current().column() \ + >::guidepost.send_guidance(json_pairs); \ +} while (0) + +#endif + +namespace antithesis { + template + Iter random_choice(Iter begin, Iter end) { + ssize_t num_things = end - begin; + if (num_things == 0) { + return end; + } + + uint64_t uval = get_random(); + ssize_t index = uval % num_things; + return begin + index; + } +} diff --git a/include/xrpl/basics/Buffer.h b/include/xrpl/basics/Buffer.h index 25ae8ca315c..733db0bdb72 100644 --- a/include/xrpl/basics/Buffer.h +++ b/include/xrpl/basics/Buffer.h @@ -21,7 +21,7 @@ #define RIPPLE_BASICS_BUFFER_H_INCLUDED #include -#include +#include #include #include #include @@ -112,9 +112,10 @@ class Buffer operator=(Slice s) { // Ensure the slice isn't a subset of the buffer. - assert( + ASSERT( s.size() == 0 || size_ == 0 || s.data() < p_.get() || - s.data() >= p_.get() + size_); + s.data() >= p_.get() + size_, + "ripple::Buffer::operator=(Slice) : input not a subset"); if (auto p = alloc(s.size())) std::memcpy(p, s.data(), s.size()); diff --git a/include/xrpl/basics/FeeUnits.h b/include/xrpl/basics/FeeUnits.h index c63a169f00e..70f2fc9fa89 100644 --- a/include/xrpl/basics/FeeUnits.h +++ b/include/xrpl/basics/FeeUnits.h @@ -20,16 +20,16 @@ #define BASICS_FEES_H_INCLUDED #include +#include #include -#include -#include -#include #include #include #include +#include #include #include +#include namespace ripple { @@ -419,9 +419,13 @@ mulDivU(Source1 value, Dest mul, Source2 div) { // split the asserts so if one hits, the user can tell which // without a debugger. - assert(value.value() >= 0); - assert(mul.value() >= 0); - assert(div.value() >= 0); + ASSERT( + value.value() >= 0, + "ripple::feeunit::mulDivU : minimum value input"); + ASSERT( + mul.value() >= 0, "ripple::feeunit::mulDivU : minimum mul input"); + ASSERT( + div.value() >= 0, "ripple::feeunit::mulDivU : minimum div input"); return std::nullopt; } diff --git a/include/xrpl/basics/MathUtilities.h b/include/xrpl/basics/MathUtilities.h index 4e8e3751cd8..45b8fc485cc 100644 --- a/include/xrpl/basics/MathUtilities.h +++ b/include/xrpl/basics/MathUtilities.h @@ -43,7 +43,7 @@ namespace ripple { constexpr std::size_t calculatePercent(std::size_t count, std::size_t total) { - assert(total != 0); + assert(total != 0); // NOTE No ASSERT here, because constexpr return ((std::min(count, total) * 100) + total - 1) / total; } diff --git a/include/xrpl/basics/SlabAllocator.h b/include/xrpl/basics/SlabAllocator.h index 5c4cba343cf..147231299e7 100644 --- a/include/xrpl/basics/SlabAllocator.h +++ b/include/xrpl/basics/SlabAllocator.h @@ -20,7 +20,9 @@ #ifndef RIPPLE_BASICS_SLABALLOCATOR_H_INCLUDED #define RIPPLE_BASICS_SLABALLOCATOR_H_INCLUDED +#include #include +#include #include #include @@ -28,10 +30,10 @@ #include #include -#include #include #include #include +#include #if BOOST_OS_LINUX #include @@ -141,7 +143,9 @@ class SlabAllocator void deallocate(std::uint8_t* ptr) noexcept { - assert(own(ptr)); + ASSERT( + own(ptr), + "ripple::SlabAllocator::SlabBlock::deallocate : own input"); std::lock_guard l(m_); @@ -184,7 +188,9 @@ class SlabAllocator boost::alignment::align_up(sizeof(Type) + extra, itemAlignment_)) , slabSize_(alloc) { - assert((itemAlignment_ & (itemAlignment_ - 1)) == 0); + ASSERT( + (itemAlignment_ & (itemAlignment_ - 1)) == 0, + "ripple::SlabAllocator::SlabAllocator : valid alignment"); } SlabAllocator(SlabAllocator const& other) = delete; @@ -294,7 +300,10 @@ class SlabAllocator bool deallocate(std::uint8_t* ptr) noexcept { - assert(ptr); + ASSERT( + ptr != nullptr, + "ripple::SlabAllocator::SlabAllocator::deallocate : non-null " + "input"); for (auto slab = slabs_.load(); slab != nullptr; slab = slab->next_) { diff --git a/include/xrpl/basics/Slice.h b/include/xrpl/basics/Slice.h index 00126f8882d..c10ca0b0e96 100644 --- a/include/xrpl/basics/Slice.h +++ b/include/xrpl/basics/Slice.h @@ -22,9 +22,9 @@ #include #include +#include #include #include -#include #include #include #include @@ -103,7 +103,9 @@ class Slice std::uint8_t operator[](std::size_t i) const noexcept { - assert(i < size_); + ASSERT( + i < size_, + "ripple::Slice::operator[](std::size_t) const : valid input"); return data_[i]; } diff --git a/include/xrpl/basics/base_uint.h b/include/xrpl/basics/base_uint.h index ae5aa17a63e..9adb3b394c4 100644 --- a/include/xrpl/basics/base_uint.h +++ b/include/xrpl/basics/base_uint.h @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -289,7 +290,9 @@ class base_uint std::is_trivially_copyable::value>> explicit base_uint(Container const& c) { - assert(c.size() * sizeof(typename Container::value_type) == size()); + ASSERT( + c.size() * sizeof(typename Container::value_type) == size(), + "ripple::base_uint::base_uint(Container auto) : input size match"); std::memcpy(data_.data(), c.data(), size()); } @@ -300,7 +303,9 @@ class base_uint base_uint&> operator=(Container const& c) { - assert(c.size() * sizeof(typename Container::value_type) == size()); + ASSERT( + c.size() * sizeof(typename Container::value_type) == size(), + "ripple::base_uint::operator=(Container auto) : input size match"); std::memcpy(data_.data(), c.data(), size()); return *this; } diff --git a/include/xrpl/basics/partitioned_unordered_map.h b/include/xrpl/basics/partitioned_unordered_map.h index 08f4cba9d3e..c8e31906dc4 100644 --- a/include/xrpl/basics/partitioned_unordered_map.h +++ b/include/xrpl/basics/partitioned_unordered_map.h @@ -20,7 +20,7 @@ #ifndef RIPPLE_BASICS_PARTITIONED_UNORDERED_MAP_H #define RIPPLE_BASICS_PARTITIONED_UNORDERED_MAP_H -#include +#include #include #include #include @@ -246,7 +246,10 @@ class partitioned_unordered_map ? *partitions : std::thread::hardware_concurrency(); map_.resize(partitions_); - assert(partitions_); + ASSERT( + partitions_ != 0, + "ripple::partitioned_unordered_map::partitioned_unordered_map : " + "nonzero partitions"); } std::size_t diff --git a/include/xrpl/basics/random.h b/include/xrpl/basics/random.h index 87b303bf6d5..41369d2a454 100644 --- a/include/xrpl/basics/random.h +++ b/include/xrpl/basics/random.h @@ -20,8 +20,8 @@ #ifndef RIPPLE_BASICS_RANDOM_H_INCLUDED #define RIPPLE_BASICS_RANDOM_H_INCLUDED +#include #include -#include #include #include #include @@ -114,7 +114,7 @@ std::enable_if_t< Integral> rand_int(Engine& engine, Integral min, Integral max) { - assert(max > min); + ASSERT(max > min, "ripple::rand_int : max over min inputs"); // This should have no state and constructing it should // be very cheap. If that turns out not to be the case diff --git a/include/xrpl/basics/scope.h b/include/xrpl/basics/scope.h index b1d13eae8ce..a38184041c6 100644 --- a/include/xrpl/basics/scope.h +++ b/include/xrpl/basics/scope.h @@ -20,6 +20,8 @@ #ifndef RIPPLE_BASICS_SCOPE_H_INCLUDED #define RIPPLE_BASICS_SCOPE_H_INCLUDED +#include + #include #include #include @@ -233,7 +235,9 @@ class scope_unlock explicit scope_unlock(std::unique_lock& lock) noexcept(true) : plock(&lock) { - assert(plock->owns_lock()); + ASSERT( + plock->owns_lock(), + "ripple::scope_unlock::scope_unlock : mutex must be locked"); plock->unlock(); } diff --git a/include/xrpl/basics/spinlock.h b/include/xrpl/basics/spinlock.h index 85a2ac41d51..92514478c4f 100644 --- a/include/xrpl/basics/spinlock.h +++ b/include/xrpl/basics/spinlock.h @@ -18,8 +18,8 @@ #ifndef RIPPLE_BASICS_SPINLOCK_H_INCLUDED #define RIPPLE_BASICS_SPINLOCK_H_INCLUDED +#include #include -#include #include #include @@ -117,7 +117,9 @@ class packed_spinlock packed_spinlock(std::atomic& lock, int index) : bits_(lock), mask_(static_cast(1) << index) { - assert(index >= 0 && (mask_ != 0)); + ASSERT( + index >= 0 && (mask_ != 0), + "ripple::packed_spinlock::packed_spinlock : valid index and mask"); } [[nodiscard]] bool diff --git a/include/xrpl/beast/asio/io_latency_probe.h b/include/xrpl/beast/asio/io_latency_probe.h index bbde13af687..fb4f5f9f6a2 100644 --- a/include/xrpl/beast/asio/io_latency_probe.h +++ b/include/xrpl/beast/asio/io_latency_probe.h @@ -20,8 +20,10 @@ #ifndef BEAST_ASIO_IO_LATENCY_PROBE_H_INCLUDED #define BEAST_ASIO_IO_LATENCY_PROBE_H_INCLUDED +#include #include #include + #include #include #include @@ -172,7 +174,10 @@ class io_latency_probe , m_repeat(repeat) , m_probe(probe) { - assert(m_probe); + ASSERT( + m_probe != nullptr, + "beast::io_latency_probe::sample_op::sample_op : non-null " + "probe input"); m_probe->addref(); } @@ -182,7 +187,10 @@ class io_latency_probe , m_repeat(from.m_repeat) , m_probe(from.m_probe) { - assert(m_probe); + ASSERT( + m_probe != nullptr, + "beast::io_latency_probe::sample_op::sample_op(sample_op&&) : " + "non-null probe input"); from.m_probe = nullptr; } diff --git a/include/xrpl/beast/clock/manual_clock.h b/include/xrpl/beast/clock/manual_clock.h index 97be8e79b90..505cbe27208 100644 --- a/include/xrpl/beast/clock/manual_clock.h +++ b/include/xrpl/beast/clock/manual_clock.h @@ -21,7 +21,7 @@ #define BEAST_CHRONO_MANUAL_CLOCK_H_INCLUDED #include -#include +#include namespace beast { @@ -61,7 +61,9 @@ class manual_clock : public abstract_clock void set(time_point const& when) { - assert(!Clock::is_steady || when >= now_); + ASSERT( + !Clock::is_steady || when >= now_, + "beast::manual_clock::set(time_point) : forward input"); now_ = when; } @@ -78,7 +80,9 @@ class manual_clock : public abstract_clock void advance(std::chrono::duration const& elapsed) { - assert(!Clock::is_steady || (now_ + elapsed) >= now_); + ASSERT( + !Clock::is_steady || (now_ + elapsed) >= now_, + "beast::manual_clock::advance(duration) : forward input"); now_ += elapsed; } diff --git a/include/xrpl/beast/container/detail/aged_unordered_container.h b/include/xrpl/beast/container/detail/aged_unordered_container.h index 72e3334801b..30c8489693e 100644 --- a/include/xrpl/beast/container/detail/aged_unordered_container.h +++ b/include/xrpl/beast/container/detail/aged_unordered_container.h @@ -1330,7 +1330,10 @@ class aged_unordered_container size_type bucket(Key const& k) const { - assert(bucket_count() != 0); + ASSERT( + bucket_count() != 0, + "beast::detail::aged_unordered_container::bucket : nonzero bucket " + "count"); return m_cont.bucket(k, std::cref(m_config.hash_function())); } @@ -1471,7 +1474,10 @@ class aged_unordered_container { if (would_exceed(additional)) m_buck.resize(size() + additional, m_cont); - assert(load_factor() <= max_load_factor()); + ASSERT( + load_factor() <= max_load_factor(), + "beast::detail::aged_unordered_container::maybe_rehash : maximum " + "load factor"); } // map, set diff --git a/include/xrpl/beast/core/LexicalCast.h b/include/xrpl/beast/core/LexicalCast.h index e0fa24ca9f5..0a7f2379daf 100644 --- a/include/xrpl/beast/core/LexicalCast.h +++ b/include/xrpl/beast/core/LexicalCast.h @@ -20,9 +20,10 @@ #ifndef BEAST_MODULE_CORE_TEXT_LEXICALCAST_H_INCLUDED #define BEAST_MODULE_CORE_TEXT_LEXICALCAST_H_INCLUDED +#include + #include #include -#include #include #include #include @@ -159,7 +160,9 @@ struct LexicalCast bool operator()(Out& out, char const* in) const { - assert(in); + ASSERT( + in != nullptr, + "beast::detail::LexicalCast(char const*) : non-null input"); return LexicalCast()(out, in); } }; @@ -174,7 +177,9 @@ struct LexicalCast bool operator()(Out& out, char* in) const { - assert(in); + ASSERT( + in != nullptr, + "beast::detail::LexicalCast(char*) : non-null input"); return LexicalCast()(out, in); } }; diff --git a/include/xrpl/beast/net/IPAddress.h b/include/xrpl/beast/net/IPAddress.h index f3a1a7348f2..cdac4abbd9c 100644 --- a/include/xrpl/beast/net/IPAddress.h +++ b/include/xrpl/beast/net/IPAddress.h @@ -24,9 +24,9 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -96,7 +96,7 @@ hash_append(Hasher& h, beast::IP::Address const& addr) noexcept else if (addr.is_v6()) hash_append(h, addr.to_v6().to_bytes()); else - assert(false); + UNREACHABLE("beast::hash_append : invalid address type"); } } // namespace beast diff --git a/include/xrpl/beast/net/IPAddressV6.h b/include/xrpl/beast/net/IPAddressV6.h index 74eb6b96d8e..83e4d6f8a32 100644 --- a/include/xrpl/beast/net/IPAddressV6.h +++ b/include/xrpl/beast/net/IPAddressV6.h @@ -20,8 +20,8 @@ #ifndef BEAST_NET_IPADDRESSV6_H_INCLUDED #define BEAST_NET_IPADDRESSV6_H_INCLUDED +#include #include -#include #include #include #include diff --git a/include/xrpl/beast/utility/Journal.h b/include/xrpl/beast/utility/Journal.h index 059355ccae7..aaa53a3515d 100644 --- a/include/xrpl/beast/utility/Journal.h +++ b/include/xrpl/beast/utility/Journal.h @@ -20,7 +20,7 @@ #ifndef BEAST_UTILITY_JOURNAL_H_INCLUDED #define BEAST_UTILITY_JOURNAL_H_INCLUDED -#include +#include #include namespace beast { @@ -205,7 +205,9 @@ class Journal */ Stream(Sink& sink, Severity level) : m_sink(sink), m_level(level) { - assert(m_level < severities::kDisabled); + ASSERT( + m_level < severities::kDisabled, + "beast::Journal::Stream::Stream : maximum level"); } /** Construct or copy another Stream. */ diff --git a/include/xrpl/beast/utility/instrumentation.h b/include/xrpl/beast/utility/instrumentation.h new file mode 100644 index 00000000000..f3f8987242e --- /dev/null +++ b/include/xrpl/beast/utility/instrumentation.h @@ -0,0 +1,64 @@ +//------------------------------------------------------------------------------ +/* +This file is part of rippled: https://github.com/ripple/rippled +Copyright (c) 2024 Ripple Labs Inc. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_UTILITY_INSTRUMENTATION_H_INCLUDED +#define BEAST_UTILITY_INSTRUMENTATION_H_INCLUDED + +#include + +#ifdef ENABLE_VOIDSTAR +#ifdef NDEBUG +#error "Antithesis instrumentation requires Debug build" +#endif +#include +#else +#define ALWAYS(cond, name, ...) assert((name) && (cond)) +#define ALWAYS_OR_UNREACHABLE(cond, name, ...) assert((name) && (cond)) +#define SOMETIMES(cond, name, ...) +#define REACHABLE(name, ...) +#define UNREACHABLE(name, ...) assert((name) && false) +#endif + +#define ASSERT ALWAYS_OR_UNREACHABLE + +// How to use the instrumentation macros: +// +// ALWAYS if cond must be true and the line must be reached during fuzzing +// ASSERT if cond must be true but the line might not be reached during fuzzing +// REACHABLE if the line must be reached during fuzzing +// SOMETIMES a hint for the fuzzer to try to make the cond true +// UNREACHABLE if the line must not be reached (in fuzzing or in normal use) +// +// NOTE: ASSERT has similar semantics as C assert macro, with minor differences: +// * ASSERT must have an unique name (naming convention in CONTRIBUTING.md) +// * the condition (which comes first) must be *implicitly* convertible to bool +// * during fuzzing, the program will continue execution past a failed ASSERT +// +// We continue to use regular C assert inside unit tests and inside constexpr +// functions. +// +// NOTE: UNREACHABLE does *not* have the same semantics as std::unreachable. +// The program will continue execution past an UNREACHABLE in a Release build +// and during fuzzing (similar to ASSERT). +// Also, the naming convention in UNREACHABLE is subtly different from other +// instrumentation macros - its name describes the condition which was *not* +// meant to happen, while name in other macros describe the condition that is +// meant to happen (e.g. as in "assert that this happens"). + +#endif diff --git a/include/xrpl/beast/utility/rngfill.h b/include/xrpl/beast/utility/rngfill.h index 71f434bdaf9..3be6aa307b3 100644 --- a/include/xrpl/beast/utility/rngfill.h +++ b/include/xrpl/beast/utility/rngfill.h @@ -20,8 +20,8 @@ #ifndef BEAST_RANDOM_RNGFILL_H_INCLUDED #define BEAST_RANDOM_RNGFILL_H_INCLUDED +#include #include -#include #include #include #include @@ -42,7 +42,8 @@ rngfill(void* buffer, std::size_t bytes, Generator& g) bytes -= sizeof(v); } - assert(bytes < sizeof(result_type)); + ASSERT( + bytes < sizeof(result_type), "beast::rngfill(void*) : maximum bytes"); #ifdef __GNUC__ // gcc 11.1 (falsely) warns about an array-bounds overflow in release mode. diff --git a/include/xrpl/json/detail/json_assert.h b/include/xrpl/json/detail/json_assert.h index c401ccf7200..264bcd90f3d 100644 --- a/include/xrpl/json/detail/json_assert.h +++ b/include/xrpl/json/detail/json_assert.h @@ -22,9 +22,6 @@ #include -#define JSON_ASSERT_UNREACHABLE assert(false) -#define JSON_ASSERT(condition) \ - assert(condition); // @todo <= change this into an exception throw #define JSON_ASSERT_MESSAGE(condition, message) \ if (!(condition)) \ ripple::Throw(message); diff --git a/include/xrpl/protocol/AmountConversions.h b/include/xrpl/protocol/AmountConversions.h index 270d009b916..20a985d1190 100644 --- a/include/xrpl/protocol/AmountConversions.h +++ b/include/xrpl/protocol/AmountConversions.h @@ -53,7 +53,9 @@ toSTAmount(XRPAmount const& xrp) inline STAmount toSTAmount(XRPAmount const& xrp, Issue const& iss) { - assert(isXRP(iss.account) && isXRP(iss.currency)); + ASSERT( + isXRP(iss.account) && isXRP(iss.currency), + "ripple::toSTAmount : is XRP"); return toSTAmount(xrp); } @@ -72,12 +74,14 @@ template <> inline IOUAmount toAmount(STAmount const& amt) { - assert(amt.mantissa() < std::numeric_limits::max()); + ASSERT( + amt.mantissa() < std::numeric_limits::max(), + "ripple::toAmount : maximum mantissa"); bool const isNeg = amt.negative(); std::int64_t const sMant = isNeg ? -std::int64_t(amt.mantissa()) : amt.mantissa(); - assert(!isXRP(amt)); + ASSERT(!isXRP(amt), "ripple::toAmount : is not XRP"); return IOUAmount(sMant, amt.exponent()); } @@ -85,12 +89,14 @@ template <> inline XRPAmount toAmount(STAmount const& amt) { - assert(amt.mantissa() < std::numeric_limits::max()); + ASSERT( + amt.mantissa() < std::numeric_limits::max(), + "ripple::toAmount : maximum mantissa"); bool const isNeg = amt.negative(); std::int64_t const sMant = isNeg ? -std::int64_t(amt.mantissa()) : amt.mantissa(); - assert(isXRP(amt)); + ASSERT(isXRP(amt), "ripple::toAmount : is XRP"); return XRPAmount(sMant); } diff --git a/include/xrpl/protocol/Feature.h b/include/xrpl/protocol/Feature.h index 90a81c55ef4..219230e69a1 100644 --- a/include/xrpl/protocol/Feature.h +++ b/include/xrpl/protocol/Feature.h @@ -151,14 +151,19 @@ class FeatureBitset : private std::bitset explicit FeatureBitset(base const& b) : base(b) { - assert(b.count() == count()); + ASSERT( + b.count() == count(), + "ripple::FeatureBitset::FeatureBitset(base) : count match"); } template explicit FeatureBitset(uint256 const& f, Fs&&... fs) { initFromFeatures(f, std::forward(fs)...); - assert(count() == (sizeof...(fs) + 1)); + ASSERT( + count() == (sizeof...(fs) + 1), + "ripple::FeatureBitset::FeatureBitset(uint256) : count and " + "sizeof... do match"); } template @@ -166,7 +171,10 @@ class FeatureBitset : private std::bitset { for (auto const& f : fs) set(featureToBitsetIndex(f)); - assert(fs.size() == count()); + ASSERT( + fs.size() == count(), + "ripple::FeatureBitset::FeatureBitset(Container auto) : count and " + "size do match"); } auto diff --git a/include/xrpl/protocol/Indexes.h b/include/xrpl/protocol/Indexes.h index 72cf0b527b1..6b5024a1f03 100644 --- a/include/xrpl/protocol/Indexes.h +++ b/include/xrpl/protocol/Indexes.h @@ -220,7 +220,7 @@ page(uint256 const& root, std::uint64_t index = 0) noexcept; inline Keylet page(Keylet const& root, std::uint64_t index = 0) noexcept { - assert(root.type == ltDIR_NODE); + ASSERT(root.type == ltDIR_NODE, "ripple::keylet::page : valid root type"); return page(root.key, index); } /** @} */ diff --git a/include/xrpl/protocol/Issue.h b/include/xrpl/protocol/Issue.h index 335dd91354a..60182698ee6 100644 --- a/include/xrpl/protocol/Issue.h +++ b/include/xrpl/protocol/Issue.h @@ -20,10 +20,10 @@ #ifndef RIPPLE_PROTOCOL_ISSUE_H_INCLUDED #define RIPPLE_PROTOCOL_ISSUE_H_INCLUDED +#include #include #include -#include #include #include diff --git a/include/xrpl/protocol/MultiApiJson.h b/include/xrpl/protocol/MultiApiJson.h index 73c274ff7f7..e1f65199617 100644 --- a/include/xrpl/protocol/MultiApiJson.h +++ b/include/xrpl/protocol/MultiApiJson.h @@ -23,8 +23,8 @@ #include #include +#include #include -#include #include #include #include @@ -159,8 +159,10 @@ struct MultiApiJson -> std:: invoke_result_t { - assert( - valid(version) && index(version) >= 0 && index(version) < size); + ASSERT( + valid(version) && index(version) >= 0 && index(version) < size, + "ripple::detail::MultiApiJson::operator() : valid " + "version"); return std::invoke( fn, json.val[index(version)], @@ -177,8 +179,9 @@ struct MultiApiJson operator()(Json& json, Version version, Fn fn) const -> std::invoke_result_t { - assert( - valid(version) && index(version) >= 0 && index(version) < size); + ASSERT( + valid(version) && index(version) >= 0 && index(version) < size, + "ripple::detail::MultiApiJson::operator() : valid version"); return std::invoke(fn, json.val[index(version)]); } } visitor = {}; diff --git a/include/xrpl/protocol/Quality.h b/include/xrpl/protocol/Quality.h index 1ee2cc9f686..fac9dd29a43 100644 --- a/include/xrpl/protocol/Quality.h +++ b/include/xrpl/protocol/Quality.h @@ -298,7 +298,9 @@ class Quality friend double relativeDistance(Quality const& q1, Quality const& q2) { - assert(q1.m_value > 0 && q2.m_value > 0); + ASSERT( + q1.m_value > 0 && q2.m_value > 0, + "ripple::Quality::relativeDistance : minimum inputs"); if (q1.m_value == q2.m_value) // make expected common case fast return 0; diff --git a/include/xrpl/protocol/Rate.h b/include/xrpl/protocol/Rate.h index 6970d9c16a8..2872a5809de 100644 --- a/include/xrpl/protocol/Rate.h +++ b/include/xrpl/protocol/Rate.h @@ -20,9 +20,9 @@ #ifndef RIPPLE_PROTOCOL_RATE_H_INCLUDED #define RIPPLE_PROTOCOL_RATE_H_INCLUDED +#include #include #include -#include #include #include diff --git a/include/xrpl/protocol/STAmount.h b/include/xrpl/protocol/STAmount.h index e0a6c1eca08..f3dde91cf7e 100644 --- a/include/xrpl/protocol/STAmount.h +++ b/include/xrpl/protocol/STAmount.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -353,7 +354,10 @@ STAmount::STAmount( , mIsNegative(negative) { // mValue is uint64, but needs to fit in the range of int64 - assert(mValue <= std::numeric_limits::max()); + ASSERT( + mValue <= std::numeric_limits::max(), + "ripple::STAmount::STAmount(SField, A, std::uint64_t, int, bool) : " + "maximum mantissa input"); canonicalize(); } diff --git a/include/xrpl/protocol/STBitString.h b/include/xrpl/protocol/STBitString.h index f3a74f2fc54..a80c3c2c253 100644 --- a/include/xrpl/protocol/STBitString.h +++ b/include/xrpl/protocol/STBitString.h @@ -170,8 +170,10 @@ template void STBitString::add(Serializer& s) const { - assert(getFName().isBinary()); - assert(getFName().fieldType == getSType()); + ASSERT(getFName().isBinary(), "ripple::STBitString::add : field is binary"); + ASSERT( + getFName().fieldType == getSType(), + "ripple::STBitString::add : field type match"); s.addBitString(value_); } diff --git a/include/xrpl/protocol/STBlob.h b/include/xrpl/protocol/STBlob.h index bdedbd92105..cfe4ab5af58 100644 --- a/include/xrpl/protocol/STBlob.h +++ b/include/xrpl/protocol/STBlob.h @@ -23,9 +23,9 @@ #include #include #include +#include #include -#include #include #include diff --git a/include/xrpl/protocol/STInteger.h b/include/xrpl/protocol/STInteger.h index 6bae2cc3152..8dc6b7ff1a3 100644 --- a/include/xrpl/protocol/STInteger.h +++ b/include/xrpl/protocol/STInteger.h @@ -110,8 +110,10 @@ template inline void STInteger::add(Serializer& s) const { - assert(getFName().isBinary()); - assert(getFName().fieldType == getSType()); + ASSERT(getFName().isBinary(), "ripple::STInteger::add : field is binary"); + ASSERT( + getFName().fieldType == getSType(), + "ripple::STInteger::add : field type match"); s.addInteger(value_); } diff --git a/include/xrpl/protocol/STObject.h b/include/xrpl/protocol/STObject.h index 748a2b5d685..a31058413f0 100644 --- a/include/xrpl/protocol/STObject.h +++ b/include/xrpl/protocol/STObject.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -35,7 +36,6 @@ #include #include #include -#include #include #include #include @@ -737,7 +737,8 @@ STObject::Proxy::assign(U&& u) t = dynamic_cast(st_->getPField(*f_, true)); else t = dynamic_cast(st_->makeFieldPresent(*f_)); - assert(t); + ASSERT( + t != nullptr, "ripple::STObject::Proxy::assign : type cast succeeded"); *t = std::forward(u); } @@ -1033,13 +1034,19 @@ STObject::at(TypedField const& f) const if (auto const u = dynamic_cast(b)) return u->value(); - assert(mType); - assert(b->getSType() == STI_NOTPRESENT); + ASSERT( + mType != nullptr, + "ripple::STObject::at(TypedField auto) : field template non-null"); + ASSERT( + b->getSType() == STI_NOTPRESENT, + "ripple::STObject::at(TypedField auto) : type not present"); if (mType->style(f) == soeOPTIONAL) Throw("Missing optional field: " + f.getName()); - assert(mType->style(f) == soeDEFAULT); + ASSERT( + mType->style(f) == soeDEFAULT, + "ripple::STObject::at(TypedField auto) : template style is default"); // Used to help handle the case where value_type is a const reference, // otherwise we would return the address of a temporary. @@ -1057,11 +1064,19 @@ STObject::at(OptionaledField const& of) const auto const u = dynamic_cast(b); if (!u) { - assert(mType); - assert(b->getSType() == STI_NOTPRESENT); + ASSERT( + mType != nullptr, + "ripple::STObject::at(OptionaledField auto) : field template " + "non-null"); + ASSERT( + b->getSType() == STI_NOTPRESENT, + "ripple::STObject::at(OptionaledField auto) : type not present"); if (mType->style(*of.f) == soeOPTIONAL) return std::nullopt; - assert(mType->style(*of.f) == soeDEFAULT); + ASSERT( + mType->style(*of.f) == soeDEFAULT, + "ripple::STObject::at(OptionaledField auto) : template style is " + "default"); return typename T::value_type{}; } return u->value(); diff --git a/include/xrpl/protocol/STPathSet.h b/include/xrpl/protocol/STPathSet.h index 473086368fb..754bb279238 100644 --- a/include/xrpl/protocol/STPathSet.h +++ b/include/xrpl/protocol/STPathSet.h @@ -21,11 +21,11 @@ #define RIPPLE_PROTOCOL_STPATHSET_H_INCLUDED #include +#include #include #include #include #include -#include #include #include @@ -257,7 +257,9 @@ inline STPathElement::STPathElement( is_offer_ = false; mAccountID = *account; mType |= typeAccount; - assert(mAccountID != noAccount()); + ASSERT( + mAccountID != noAccount(), + "ripple::STPathElement::STPathElement : account is set"); } if (currency) @@ -270,7 +272,9 @@ inline STPathElement::STPathElement( { mIssuerID = *issuer; mType |= typeIssuer; - assert(mIssuerID != noAccount()); + ASSERT( + mIssuerID != noAccount(), + "ripple::STPathElement::STPathElement : issuer is set"); } hash_value_ = get_hash(*this); diff --git a/include/xrpl/protocol/STValidation.h b/include/xrpl/protocol/STValidation.h index 6cae0971f51..69472f84e6d 100644 --- a/include/xrpl/protocol/STValidation.h +++ b/include/xrpl/protocol/STValidation.h @@ -22,10 +22,10 @@ #include #include +#include #include #include #include -#include #include #include #include @@ -176,7 +176,9 @@ STValidation::STValidation( Throw("Invalid signature in validation"); } - assert(nodeID_.isNonZero()); + ASSERT( + nodeID_.isNonZero(), + "ripple::STValidation::STValidation(SerialIter) : nonzero node"); } /** Construct, sign and trust a new STValidation issued by this node. @@ -199,7 +201,10 @@ STValidation::STValidation( , nodeID_(nodeID) , seenTime_(signTime) { - assert(nodeID_.isNonZero()); + ASSERT( + nodeID_.isNonZero(), + "ripple::STValidation::STValidation(PublicKey, SecretKey) : nonzero " + "node"); // First, set our own public key: if (publicKeyType(pk) != KeyType::secp256k1) diff --git a/include/xrpl/protocol/Serializer.h b/include/xrpl/protocol/Serializer.h index 0e96078ed14..e5e3907101d 100644 --- a/include/xrpl/protocol/Serializer.h +++ b/include/xrpl/protocol/Serializer.h @@ -27,9 +27,9 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -55,7 +55,9 @@ class Serializer if (size) { - assert(data != nullptr); + ASSERT( + data != nullptr, + "ripple::Serializer::Serializer(void const*) : non-null input"); std::memcpy(mData.data(), data, size); } } @@ -331,7 +333,7 @@ Serializer::addVL(Iter begin, Iter end, int len) len -= begin->size(); #endif } - assert(len == 0); + ASSERT(len == 0, "ripple::Serializer::addVL : length matches distance"); return ret; } diff --git a/include/xrpl/protocol/TxMeta.h b/include/xrpl/protocol/TxMeta.h index 7932a4c55a3..868efd854ff 100644 --- a/include/xrpl/protocol/TxMeta.h +++ b/include/xrpl/protocol/TxMeta.h @@ -116,7 +116,9 @@ class TxMeta STAmount getDeliveredAmount() const { - assert(hasDeliveredAmount()); + ASSERT( + hasDeliveredAmount(), + "ripple::TxMeta::getDeliveredAmount : non-null delivered amount"); return *mDelivered; } diff --git a/include/xrpl/protocol/detail/b58_utils.h b/include/xrpl/protocol/detail/b58_utils.h index b060fc7e166..960b3d8dcb6 100644 --- a/include/xrpl/protocol/detail/b58_utils.h +++ b/include/xrpl/protocol/detail/b58_utils.h @@ -21,12 +21,12 @@ #define RIPPLE_PROTOCOL_B58_UTILS_H_INCLUDED #include +#include #include #include #include -#include #include #include #include @@ -130,7 +130,9 @@ inplace_bigint_div_rem(std::span numerator, std::uint64_t divisor) { // 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. - assert(0); + UNREACHABLE( + "ripple::b58_fast::detail::inplace_bigint_div_rem : empty " + "numerator"); return 0; } @@ -146,8 +148,14 @@ inplace_bigint_div_rem(std::span numerator, std::uint64_t divisor) unsigned __int128 const denom128 = denom; unsigned __int128 const d = num / denom128; unsigned __int128 const r = num - (denom128 * d); - assert(d >> 64 == 0); - assert(r >> 64 == 0); + ASSERT( + d >> 64 == 0, + "ripple::b58_fast::detail::inplace_bigint_div_rem::div_rem_64 : " + "valid division result"); + ASSERT( + r >> 64 == 0, + "ripple::b58_fast::detail::inplace_bigint_div_rem::div_rem_64 : " + "valid remainder"); return {static_cast(d), static_cast(r)}; }; @@ -170,7 +178,9 @@ inplace_bigint_div_rem(std::span numerator, std::uint64_t divisor) b58_10_to_b58_be(std::uint64_t input) { constexpr std::uint64_t B_58_10 = 430804206899405824; // 58^10; - assert(input < B_58_10); + ASSERT( + input < B_58_10, + "ripple::b58_fast::detail::b58_10_to_b58_be : valid input"); constexpr std::size_t resultSize = 10; std::array result{}; int i = 0; diff --git a/include/xrpl/resource/detail/Entry.h b/include/xrpl/resource/detail/Entry.h index d4f32080d9d..32ba77c6d35 100644 --- a/include/xrpl/resource/detail/Entry.h +++ b/include/xrpl/resource/detail/Entry.h @@ -23,9 +23,9 @@ #include #include #include +#include #include #include -#include namespace ripple { namespace Resource { diff --git a/include/xrpl/resource/detail/Key.h b/include/xrpl/resource/detail/Key.h index 3df2dce039d..f953d5103eb 100644 --- a/include/xrpl/resource/detail/Key.h +++ b/include/xrpl/resource/detail/Key.h @@ -21,8 +21,8 @@ #define RIPPLE_RESOURCE_KEY_H_INCLUDED #include +#include #include -#include namespace ripple { namespace Resource { diff --git a/include/xrpl/resource/detail/Logic.h b/include/xrpl/resource/detail/Logic.h index a57e529e0a2..6b7830c07cd 100644 --- a/include/xrpl/resource/detail/Logic.h +++ b/include/xrpl/resource/detail/Logic.h @@ -26,12 +26,12 @@ #include #include #include +#include #include #include #include #include #include -#include #include namespace ripple { @@ -401,7 +401,9 @@ class Logic { std::lock_guard _(lock_); Entry& entry(iter->second); - assert(entry.refcount == 0); + ASSERT( + entry.refcount == 0, + "ripple::Resource::Logic::erase : entry not used"); inactive_.erase(inactive_.iterator_to(entry)); table_.erase(iter); } @@ -433,7 +435,9 @@ class Logic admin_.erase(admin_.iterator_to(entry)); break; default: - assert(false); + UNREACHABLE( + "ripple::Resource::Logic::release : invalid entry " + "kind"); break; } inactive_.push_back(entry); diff --git a/include/xrpl/server/detail/BaseHTTPPeer.h b/include/xrpl/server/detail/BaseHTTPPeer.h index 32ec4d3009d..bcdddcc711d 100644 --- a/include/xrpl/server/detail/BaseHTTPPeer.h +++ b/include/xrpl/server/detail/BaseHTTPPeer.h @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -34,7 +35,6 @@ #include #include #include -#include #include #include #include diff --git a/include/xrpl/server/detail/BasePeer.h b/include/xrpl/server/detail/BasePeer.h index a90eaabf6e4..97ad77f7f22 100644 --- a/include/xrpl/server/detail/BasePeer.h +++ b/include/xrpl/server/detail/BasePeer.h @@ -21,12 +21,12 @@ #define RIPPLE_SERVER_BASEPEER_H_INCLUDED #include +#include #include #include #include #include #include -#include #include #include diff --git a/include/xrpl/server/detail/BaseWSPeer.h b/include/xrpl/server/detail/BaseWSPeer.h index 4c4049a8b9b..8f3022bdf32 100644 --- a/include/xrpl/server/detail/BaseWSPeer.h +++ b/include/xrpl/server/detail/BaseWSPeer.h @@ -21,17 +21,21 @@ #define RIPPLE_SERVER_BASEWSPEER_H_INCLUDED #include +#include #include #include #include +#include #include #include + #include #include #include +#include -#include #include +#include namespace ripple { @@ -508,7 +512,9 @@ template void BaseWSPeer::fail(error_code ec, String const& what) { - assert(strand_.running_in_this_thread()); + ASSERT( + strand_.running_in_this_thread(), + "ripple::BaseWSPeer::fail : strand in this thread"); cancel_timer(); if (!ec_ && ec != boost::asio::error::operation_aborted) diff --git a/src/libxrpl/basics/Log.cpp b/src/libxrpl/basics/Log.cpp index 3d5963cc266..873087bd217 100644 --- a/src/libxrpl/basics/Log.cpp +++ b/src/libxrpl/basics/Log.cpp @@ -20,8 +20,8 @@ #include #include #include +#include #include -#include #include #include #include @@ -224,7 +224,7 @@ Logs::fromSeverity(beast::severities::Severity level) return lsERROR; default: - assert(false); + UNREACHABLE("ripple::Logs::fromSeverity : invalid severity"); [[fallthrough]]; case kFatal: break; @@ -250,7 +250,7 @@ Logs::toSeverity(LogSeverity level) case lsERROR: return kError; default: - assert(false); + UNREACHABLE("ripple::Logs::toSeverity : invalid severity"); [[fallthrough]]; case lsFATAL: break; @@ -277,7 +277,7 @@ Logs::toString(LogSeverity s) case lsFATAL: return "Fatal"; default: - assert(false); + UNREACHABLE("ripple::Logs::toString : invalid severity"); return "Unknown"; } } @@ -341,7 +341,7 @@ Logs::format( output += "ERR "; break; default: - assert(false); + UNREACHABLE("ripple::Logs::format : invalid severity"); [[fallthrough]]; case kFatal: output += "FTL "; diff --git a/src/libxrpl/basics/Number.cpp b/src/libxrpl/basics/Number.cpp index ebbfa0023c9..f9d10ec14e5 100644 --- a/src/libxrpl/basics/Number.cpp +++ b/src/libxrpl/basics/Number.cpp @@ -18,9 +18,9 @@ //============================================================================== #include +#include #include #include -#include #include #include #include @@ -235,7 +235,9 @@ Number::operator+=(Number const& y) *this = Number{}; return *this; } - assert(isnormal() && y.isnormal()); + ASSERT( + isnormal() && y.isnormal(), + "ripple::Number::operator+=(Number) : is normal"); auto xm = mantissa(); auto xe = exponent(); int xn = 1; @@ -374,7 +376,9 @@ Number::operator*=(Number const& y) *this = y; return *this; } - assert(isnormal() && y.isnormal()); + ASSERT( + isnormal() && y.isnormal(), + "ripple::Number::operator*=(Number) : is normal"); auto xm = mantissa(); auto xe = exponent(); int xn = 1; @@ -428,7 +432,9 @@ Number::operator*=(Number const& y) std::to_string(xe)); mantissa_ = xm * zn; exponent_ = xe; - assert(isnormal() || *this == Number{}); + ASSERT( + isnormal() || *this == Number{}, + "ripple::Number::operator*=(Number) : result is normal"); return *this; } @@ -536,7 +542,7 @@ to_string(Number const& amount) negative = true; } - assert(exponent + 43 > 0); + ASSERT(exponent + 43 > 0, "ripple::to_string(Number) : minimum exponent"); ptrdiff_t const pad_prefix = 27; ptrdiff_t const pad_suffix = 23; @@ -562,7 +568,9 @@ to_string(Number const& amount) if (std::distance(pre_from, pre_to) > pad_prefix) pre_from += pad_prefix; - assert(post_to >= post_from); + ASSERT( + post_to >= post_from, + "ripple::to_string(Number) : first distance check"); pre_from = std::find_if(pre_from, pre_to, [](char c) { return c != '0'; }); @@ -571,7 +579,9 @@ to_string(Number const& amount) if (std::distance(post_from, post_to) > pad_suffix) post_to -= pad_suffix; - assert(post_to >= post_from); + ASSERT( + post_to >= post_from, + "ripple::to_string(Number) : second distance check"); post_to = std::find_if( std::make_reverse_iterator(post_to), diff --git a/src/libxrpl/basics/ResolverAsio.cpp b/src/libxrpl/basics/ResolverAsio.cpp index 7105eb12a74..efaaf80b5af 100644 --- a/src/libxrpl/basics/ResolverAsio.cpp +++ b/src/libxrpl/basics/ResolverAsio.cpp @@ -21,9 +21,9 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -48,7 +48,9 @@ class AsyncObject ~AsyncObject() { // Destroying the object with I/O pending? Not a clean exit! - assert(m_pending.load() == 0); + ASSERT( + m_pending.load() == 0, + "ripple::AsyncObject::~AsyncObject : nothing pending"); } /** RAII container that maintains the count of pending I/O. @@ -153,8 +155,11 @@ class ResolverAsioImpl : public ResolverAsio, ~ResolverAsioImpl() override { - assert(m_work.empty()); - assert(m_stopped); + ASSERT( + m_work.empty(), + "ripple::ResolverAsioImpl::~ResolverAsioImpl : no pending work"); + ASSERT( + m_stopped, "ripple::ResolverAsioImpl::~ResolverAsioImpl : stopped"); } //------------------------------------------------------------------------- @@ -176,8 +181,10 @@ class ResolverAsioImpl : public ResolverAsio, void start() override { - assert(m_stopped == true); - assert(m_stop_called == false); + ASSERT(m_stopped == true, "ripple::ResolverAsioImpl::start : stopped"); + ASSERT( + m_stop_called == false, + "ripple::ResolverAsioImpl::start : not stopping"); if (m_stopped.exchange(false) == true) { @@ -217,8 +224,12 @@ class ResolverAsioImpl : public ResolverAsio, resolve(std::vector const& names, HandlerType const& handler) override { - assert(m_stop_called == false); - assert(!names.empty()); + ASSERT( + m_stop_called == false, + "ripple::ResolverAsioImpl::resolve : not stopping"); + ASSERT( + !names.empty(), + "ripple::ResolverAsioImpl::resolve : names non-empty"); // TODO NIKB use rvalue references to construct and move // reducing cost. @@ -235,7 +246,9 @@ class ResolverAsioImpl : public ResolverAsio, void do_stop(CompletionCounter) { - assert(m_stop_called == true); + ASSERT( + m_stop_called == true, + "ripple::ResolverAsioImpl::do_stop : stopping"); if (m_stopped.exchange(true) == false) { @@ -381,7 +394,9 @@ class ResolverAsioImpl : public ResolverAsio, HandlerType const& handler, CompletionCounter) { - assert(!names.empty()); + ASSERT( + !names.empty(), + "ripple::ResolverAsioImpl::do_resolve : names non-empty"); if (m_stop_called == false) { diff --git a/src/libxrpl/basics/contract.cpp b/src/libxrpl/basics/contract.cpp index fbda83c7a63..4f0a74644af 100644 --- a/src/libxrpl/basics/contract.cpp +++ b/src/libxrpl/basics/contract.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -48,6 +49,12 @@ LogicError(std::string const& s) noexcept { JLOG(debugLog().fatal()) << s; std::cerr << "Logic error: " << s << std::endl; + // Use a non-standard contract naming here (without namespace) because + // it's the only location where various unrelated execution paths may + // register an error; this is also why the "message" parameter is passed + // here. + // For the above reasons, we want this contract to stand out. + UNREACHABLE("LogicError", {{"message", s}}); detail::accessViolation(); } diff --git a/src/libxrpl/beast/clock/basic_seconds_clock.cpp b/src/libxrpl/beast/clock/basic_seconds_clock.cpp index f5af8bd16ec..fa9a8725df5 100644 --- a/src/libxrpl/beast/clock/basic_seconds_clock.cpp +++ b/src/libxrpl/beast/clock/basic_seconds_clock.cpp @@ -18,9 +18,9 @@ //============================================================================== #include +#include #include -#include #include #include #include @@ -57,7 +57,9 @@ static_assert(std::atomic::is_always_lock_free); seconds_clock_thread::~seconds_clock_thread() { - assert(thread_.joinable()); + ASSERT( + thread_.joinable(), + "beast::seconds_clock_thread::~seconds_clock_thread : thread joinable"); { std::lock_guard lock(mut_); stop_ = true; diff --git a/src/libxrpl/beast/core/SemanticVersion.cpp b/src/libxrpl/beast/core/SemanticVersion.cpp index b33ed2f48f4..e4a5aee486a 100644 --- a/src/libxrpl/beast/core/SemanticVersion.cpp +++ b/src/libxrpl/beast/core/SemanticVersion.cpp @@ -19,9 +19,9 @@ #include #include +#include #include -#include #include namespace beast { @@ -304,7 +304,8 @@ compare(SemanticVersion const& lhs, SemanticVersion const& rhs) if (isNumeric(left)) { - assert(isNumeric(right)); + ASSERT( + isNumeric(right), "beast::compare : both inputs numeric"); int const iLeft(lexicalCastThrow(left)); int const iRight(lexicalCastThrow(right)); @@ -316,7 +317,9 @@ compare(SemanticVersion const& lhs, SemanticVersion const& rhs) } else { - assert(!isNumeric(right)); + ASSERT( + !isNumeric(right), + "beast::compare : both inputs non-numeric"); int result = left.compare(right); diff --git a/src/libxrpl/beast/insight/StatsDCollector.cpp b/src/libxrpl/beast/insight/StatsDCollector.cpp index 76ae15b82d5..58322fc95ed 100644 --- a/src/libxrpl/beast/insight/StatsDCollector.cpp +++ b/src/libxrpl/beast/insight/StatsDCollector.cpp @@ -25,8 +25,8 @@ #include #include #include +#include #include -#include #include #include #include @@ -400,7 +400,10 @@ class StatsDCollectorImp for (auto const& s : *keepAlive) { std::size_t const length(s.size()); - assert(!s.empty()); + ASSERT( + !s.empty(), + "beast::insight::detail::StatsDCollectorImp::send_buffers : " + "non-empty payload"); if (!buffers.empty() && (size + length) > max_packet_size) { log(buffers); diff --git a/src/libxrpl/beast/utility/src/beast_Journal.cpp b/src/libxrpl/beast/utility/src/beast_Journal.cpp index 8ce7ea8d47c..449f474739c 100644 --- a/src/libxrpl/beast/utility/src/beast_Journal.cpp +++ b/src/libxrpl/beast/utility/src/beast_Journal.cpp @@ -18,7 +18,7 @@ //============================================================================== #include -#include +#include namespace beast { diff --git a/src/libxrpl/beast/utility/src/beast_PropertyStream.cpp b/src/libxrpl/beast/utility/src/beast_PropertyStream.cpp index 56e862ca8c0..46c17ea4644 100644 --- a/src/libxrpl/beast/utility/src/beast_PropertyStream.cpp +++ b/src/libxrpl/beast/utility/src/beast_PropertyStream.cpp @@ -18,8 +18,8 @@ //============================================================================== #include +#include #include -#include #include #include @@ -199,7 +199,9 @@ PropertyStream::Source::add(Source& source) std::lock_guard lk1(lock_, std::adopt_lock); std::lock_guard lk2(source.lock_, std::adopt_lock); - assert(source.parent_ == nullptr); + ASSERT( + source.parent_ == nullptr, + "beast::PropertyStream::Source::add : null source parent"); children_.push_back(source.item_); source.parent_ = this; } @@ -211,7 +213,9 @@ PropertyStream::Source::remove(Source& child) std::lock_guard lk1(lock_, std::adopt_lock); std::lock_guard lk2(child.lock_, std::adopt_lock); - assert(child.parent_ == this); + ASSERT( + child.parent_ == this, + "beast::PropertyStream::Source::remove : child parent match"); children_.erase(children_.iterator_to(child.item_)); child.parent_ = nullptr; } diff --git a/src/libxrpl/crypto/RFC1751.cpp b/src/libxrpl/crypto/RFC1751.cpp index 1c6f28287b0..35363c862b5 100644 --- a/src/libxrpl/crypto/RFC1751.cpp +++ b/src/libxrpl/crypto/RFC1751.cpp @@ -17,10 +17,10 @@ */ //============================================================================== +#include #include #include #include -#include #include #include @@ -270,10 +270,12 @@ RFC1751::extract(char const* s, int start, int length) unsigned char cr; unsigned long x; - assert(length <= 11); - assert(start >= 0); - assert(length >= 0); - assert(start + length <= 66); + ASSERT(length <= 11, "ripple::RFC1751::extract : maximum length"); + ASSERT(start >= 0, "ripple::RFC1751::extract : minimum start"); + ASSERT(length >= 0, "ripple::RFC1751::extract : minimum length"); + ASSERT( + start + length <= 66, + "ripple::RFC1751::extract : maximum start + length"); int const shiftR = 24 - (length + (start % 8)); cl = s[start / 8]; // get components @@ -320,10 +322,12 @@ RFC1751::insert(char* s, int x, int start, int length) unsigned long y; int shift; - assert(length <= 11); - assert(start >= 0); - assert(length >= 0); - assert(start + length <= 66); + ASSERT(length <= 11, "ripple::RFC1751::insert : maximum length"); + ASSERT(start >= 0, "ripple::RFC1751::insert : minimum start"); + ASSERT(length >= 0, "ripple::RFC1751::insert : minimum length"); + ASSERT( + start + length <= 66, + "ripple::RFC1751::insert : maximum start + length"); shift = ((8 - ((start + length) % 8)) % 8); y = (long)x << shift; diff --git a/src/libxrpl/crypto/csprng.cpp b/src/libxrpl/crypto/csprng.cpp index 480d561eacf..948500734c0 100644 --- a/src/libxrpl/crypto/csprng.cpp +++ b/src/libxrpl/crypto/csprng.cpp @@ -18,9 +18,9 @@ //============================================================================== #include +#include #include #include -#include #include #include #include diff --git a/src/libxrpl/json/Object.cpp b/src/libxrpl/json/Object.cpp index 179b0e31ef2..d38132b1f21 100644 --- a/src/libxrpl/json/Object.cpp +++ b/src/libxrpl/json/Object.cpp @@ -18,8 +18,8 @@ //============================================================================== #include +#include #include -#include namespace Json { @@ -168,7 +168,7 @@ Array::append(Json::Value const& v) return; } } - assert(false); // Can't get here. + UNREACHABLE("Json::Array::append : invalid type"); } void @@ -203,7 +203,7 @@ Object::set(std::string const& k, Json::Value const& v) return; } } - assert(false); // Can't get here. + UNREACHABLE("Json::Object::set : invalid type"); } //------------------------------------------------------------------------------ @@ -214,7 +214,7 @@ template void doCopyFrom(Object& to, Json::Value const& from) { - assert(from.isObjectOrNull()); + ASSERT(from.isObjectOrNull(), "Json::doCopyFrom : valid input type"); auto members = from.getMemberNames(); for (auto& m : members) to[m] = from[m]; diff --git a/src/libxrpl/json/json_reader.cpp b/src/libxrpl/json/json_reader.cpp index 42488b3ec87..3e445ab5cc8 100644 --- a/src/libxrpl/json/json_reader.cpp +++ b/src/libxrpl/json/json_reader.cpp @@ -953,7 +953,7 @@ operator>>(std::istream& sin, Value& root) Json::Reader reader; bool ok = reader.parse(sin, root); - // JSON_ASSERT( ok ); + // ASSERT(ok, "Json::operator>>() : parse succeeded"); if (!ok) ripple::Throw(reader.getFormatedErrorMessages()); diff --git a/src/libxrpl/json/json_value.cpp b/src/libxrpl/json/json_value.cpp index 155c3e1e044..a2034f471c4 100644 --- a/src/libxrpl/json/json_value.cpp +++ b/src/libxrpl/json/json_value.cpp @@ -207,7 +207,7 @@ Value::Value(ValueType type) : type_(type), allocated_(0) break; default: - JSON_ASSERT_UNREACHABLE; + UNREACHABLE("Json::Value::Value(ValueType) : invalid type"); } } @@ -277,7 +277,7 @@ Value::Value(const Value& other) : type_(other.type_) break; default: - JSON_ASSERT_UNREACHABLE; + UNREACHABLE("Json::Value::Value(Value const&) : invalid type"); } } @@ -305,7 +305,7 @@ Value::~Value() break; default: - JSON_ASSERT_UNREACHABLE; + UNREACHABLE("Json::Value::~Value : invalid type"); } } @@ -406,7 +406,7 @@ operator<(const Value& x, const Value& y) } default: - JSON_ASSERT_UNREACHABLE; + UNREACHABLE("Json::operator<(Value, Value) : invalid type"); } return 0; // unreachable @@ -452,7 +452,7 @@ operator==(const Value& x, const Value& y) *x.value_.map_ == *y.value_.map_; default: - JSON_ASSERT_UNREACHABLE; + UNREACHABLE("Json::operator==(Value, Value) : invalid type"); } return 0; // unreachable @@ -461,7 +461,7 @@ operator==(const Value& x, const Value& y) const char* Value::asCString() const { - JSON_ASSERT(type_ == stringValue); + ASSERT(type_ == stringValue, "Json::Value::asCString : valid type"); return value_.string_; } @@ -493,7 +493,7 @@ Value::asString() const JSON_ASSERT_MESSAGE(false, "Type is not convertible to string"); default: - JSON_ASSERT_UNREACHABLE; + UNREACHABLE("Json::Value::asString : invalid type"); } return ""; // unreachable @@ -535,7 +535,7 @@ Value::asInt() const JSON_ASSERT_MESSAGE(false, "Type is not convertible to int"); default: - JSON_ASSERT_UNREACHABLE; + UNREACHABLE("Json::Value::asInt : invalid type"); } return 0; // unreachable; @@ -577,7 +577,7 @@ Value::asUInt() const JSON_ASSERT_MESSAGE(false, "Type is not convertible to uint"); default: - JSON_ASSERT_UNREACHABLE; + UNREACHABLE("Json::Value::asUInt : invalid type"); } return 0; // unreachable; @@ -609,7 +609,7 @@ Value::asDouble() const JSON_ASSERT_MESSAGE(false, "Type is not convertible to double"); default: - JSON_ASSERT_UNREACHABLE; + UNREACHABLE("Json::Value::asDouble : invalid type"); } return 0; // unreachable; @@ -641,7 +641,7 @@ Value::asBool() const return value_.map_->size() != 0; default: - JSON_ASSERT_UNREACHABLE; + UNREACHABLE("Json::Value::asBool : invalid type"); } return false; // unreachable; @@ -695,7 +695,7 @@ Value::isConvertibleTo(ValueType other) const (other == nullValue && value_.map_->size() == 0); default: - JSON_ASSERT_UNREACHABLE; + UNREACHABLE("Json::Value::isConvertible : invalid type"); } return false; // unreachable; @@ -729,7 +729,7 @@ Value::size() const return Int(value_.map_->size()); default: - JSON_ASSERT_UNREACHABLE; + UNREACHABLE("Json::Value::size : invalid type"); } return 0; // unreachable; @@ -752,8 +752,9 @@ Value::operator bool() const void Value::clear() { - JSON_ASSERT( - type_ == nullValue || type_ == arrayValue || type_ == objectValue); + ASSERT( + type_ == nullValue || type_ == arrayValue || type_ == objectValue, + "Json::Value::clear : valid type"); switch (type_) { @@ -770,7 +771,9 @@ Value::clear() Value& Value::operator[](UInt index) { - JSON_ASSERT(type_ == nullValue || type_ == arrayValue); + ASSERT( + type_ == nullValue || type_ == arrayValue, + "Json::Value::operator[](UInt) : valid type"); if (type_ == nullValue) *this = Value(arrayValue); @@ -789,7 +792,9 @@ Value::operator[](UInt index) const Value& Value::operator[](UInt index) const { - JSON_ASSERT(type_ == nullValue || type_ == arrayValue); + ASSERT( + type_ == nullValue || type_ == arrayValue, + "Json::Value::operator[](UInt) const : valid type"); if (type_ == nullValue) return null; @@ -812,7 +817,9 @@ Value::operator[](const char* key) Value& Value::resolveReference(const char* key, bool isStatic) { - JSON_ASSERT(type_ == nullValue || type_ == objectValue); + ASSERT( + type_ == nullValue || type_ == objectValue, + "Json::Value::resolveReference : valid type"); if (type_ == nullValue) *this = Value(objectValue); @@ -846,7 +853,9 @@ Value::isValidIndex(UInt index) const const Value& Value::operator[](const char* key) const { - JSON_ASSERT(type_ == nullValue || type_ == objectValue); + ASSERT( + type_ == nullValue || type_ == objectValue, + "Json::Value::operator[](const char*) const : valid type"); if (type_ == nullValue) return null; @@ -906,7 +915,9 @@ Value::get(std::string const& key, const Value& defaultValue) const Value Value::removeMember(const char* key) { - JSON_ASSERT(type_ == nullValue || type_ == objectValue); + ASSERT( + type_ == nullValue || type_ == objectValue, + "Json::Value::removeMember : valid type"); if (type_ == nullValue) return null; @@ -947,7 +958,9 @@ Value::isMember(std::string const& key) const Value::Members Value::getMemberNames() const { - JSON_ASSERT(type_ == nullValue || type_ == objectValue); + ASSERT( + type_ == nullValue || type_ == objectValue, + "Json::Value::getMemberNames : valid type"); if (type_ == nullValue) return Value::Members(); diff --git a/src/libxrpl/json/json_writer.cpp b/src/libxrpl/json/json_writer.cpp index 5459042cddb..3ae0dacfc2b 100644 --- a/src/libxrpl/json/json_writer.cpp +++ b/src/libxrpl/json/json_writer.cpp @@ -17,8 +17,8 @@ */ //============================================================================== +#include #include -#include #include #include #include @@ -70,7 +70,7 @@ valueToString(Int value) if (isNegative) *--current = '-'; - assert(current >= buffer); + ASSERT(current >= buffer, "Json::valueToString(Int) : buffer check"); return current; } @@ -80,7 +80,7 @@ valueToString(UInt value) char buffer[32]; char* current = buffer + sizeof(buffer); uintToString(value, current); - assert(current >= buffer); + ASSERT(current >= buffer, "Json::valueToString(UInt) : buffer check"); return current; } @@ -391,7 +391,9 @@ StyledWriter::writeArrayValue(const Value& value) } else // output on a single line { - assert(childValues_.size() == size); + ASSERT( + childValues_.size() == size, + "Json::StyledWriter::writeArrayValue : child size match"); document_ += "[ "; for (unsigned index = 0; index < size; ++index) @@ -483,7 +485,9 @@ StyledWriter::indent() void StyledWriter::unindent() { - assert(int(indentString_.size()) >= indentSize_); + ASSERT( + int(indentString_.size()) >= indentSize_, + "Json::StyledWriter::unindent : maximum indent size"); indentString_.resize(indentString_.size() - indentSize_); } @@ -613,7 +617,9 @@ StyledStreamWriter::writeArrayValue(const Value& value) } else // output on a single line { - assert(childValues_.size() == size); + ASSERT( + childValues_.size() == size, + "Json::StyledStreamWriter::writeArrayValue : child size match"); *document_ << "[ "; for (unsigned index = 0; index < size; ++index) @@ -706,7 +712,9 @@ StyledStreamWriter::indent() void StyledStreamWriter::unindent() { - assert(indentString_.size() >= indentation_.size()); + ASSERT( + indentString_.size() >= indentation_.size(), + "Json::StyledStreamWriter::unindent : maximum indent size"); indentString_.resize(indentString_.size() - indentation_.size()); } diff --git a/src/libxrpl/protocol/AMMCore.cpp b/src/libxrpl/protocol/AMMCore.cpp index 7ac27041e76..6661ab69a74 100644 --- a/src/libxrpl/protocol/AMMCore.cpp +++ b/src/libxrpl/protocol/AMMCore.cpp @@ -109,7 +109,9 @@ ammAuctionTimeSlot(std::uint64_t current, STObject const& auctionSlot) // It should be impossible for expiration to be < TOTAL_TIME_SLOT_SECS, // but check just to be safe auto const expiration = auctionSlot[sfExpiration]; - assert(expiration >= TOTAL_TIME_SLOT_SECS); + ASSERT( + expiration >= TOTAL_TIME_SLOT_SECS, + "ripple::ammAuctionTimeSlot : minimum expiration"); if (expiration >= TOTAL_TIME_SLOT_SECS) { if (auto const start = expiration - TOTAL_TIME_SLOT_SECS; diff --git a/src/libxrpl/protocol/AccountID.cpp b/src/libxrpl/protocol/AccountID.cpp index 5f0fa631851..8fe9ce115c4 100644 --- a/src/libxrpl/protocol/AccountID.cpp +++ b/src/libxrpl/protocol/AccountID.cpp @@ -77,7 +77,9 @@ class AccountIdCache auto ret = encodeBase58Token(TokenType::AccountID, id.data(), id.size()); - assert(ret.size() <= 38); + ASSERT( + ret.size() <= 38, + "ripple::detail::AccountIdCache : maximum result size"); { std::lock_guard lock(sl); diff --git a/src/libxrpl/protocol/ErrorCodes.cpp b/src/libxrpl/protocol/ErrorCodes.cpp index c157d9b296c..c9988eb589b 100644 --- a/src/libxrpl/protocol/ErrorCodes.cpp +++ b/src/libxrpl/protocol/ErrorCodes.cpp @@ -17,9 +17,9 @@ */ //============================================================================== +#include #include #include -#include #include namespace ripple { @@ -211,7 +211,9 @@ error_code_http_status(error_code_i code) std::string rpcErrorString(Json::Value const& jv) { - assert(RPC::contains_error(jv)); + ASSERT( + RPC::contains_error(jv), + "ripple::RPC::rpcErrorString : input contains an error"); return jv[jss::error].asString() + jv[jss::error_message].asString(); } diff --git a/src/libxrpl/protocol/Feature.cpp b/src/libxrpl/protocol/Feature.cpp index 3f6e760577a..47c495f9d62 100644 --- a/src/libxrpl/protocol/Feature.cpp +++ b/src/libxrpl/protocol/Feature.cpp @@ -221,7 +221,9 @@ FeatureCollections::FeatureCollections() std::optional FeatureCollections::getRegisteredFeature(std::string const& name) const { - assert(readOnly); + ASSERT( + readOnly.load(), + "ripple::FeatureCollections::getRegisteredFeature : startup completed"); Feature const* feature = getByName(name); if (feature) return feature->feature; @@ -303,7 +305,9 @@ FeatureCollections::registrationIsDone() size_t FeatureCollections::featureToBitsetIndex(uint256 const& f) const { - assert(readOnly); + ASSERT( + readOnly.load(), + "ripple::FeatureCollections::featureToBitsetIndex : startup completed"); Feature const* feature = getByFeature(f); if (!feature) @@ -315,7 +319,9 @@ FeatureCollections::featureToBitsetIndex(uint256 const& f) const uint256 const& FeatureCollections::bitsetIndexToFeature(size_t i) const { - assert(readOnly); + ASSERT( + readOnly.load(), + "ripple::FeatureCollections::bitsetIndexToFeature : startup completed"); Feature const& feature = getByIndex(i); return feature.feature; } @@ -323,7 +329,9 @@ FeatureCollections::bitsetIndexToFeature(size_t i) const std::string FeatureCollections::featureToName(uint256 const& f) const { - assert(readOnly); + ASSERT( + readOnly.load(), + "ripple::FeatureCollections::featureToName : startup completed"); Feature const* feature = getByFeature(f); return feature ? feature->name : to_string(f); } diff --git a/src/libxrpl/protocol/Indexes.cpp b/src/libxrpl/protocol/Indexes.cpp index 12142879ad5..1519673ad4a 100644 --- a/src/libxrpl/protocol/Indexes.cpp +++ b/src/libxrpl/protocol/Indexes.cpp @@ -17,6 +17,7 @@ */ //============================================================================== +#include #include #include #include @@ -26,7 +27,6 @@ #include #include -#include namespace ripple { @@ -95,7 +95,7 @@ indexHash(LedgerNameSpace space, Args const&... args) uint256 getBookBase(Book const& book) { - assert(isConsistent(book)); + ASSERT(isConsistent(book), "ripple::getBookBase : input is consistent"); auto const index = indexHash( LedgerNameSpace::BOOK_DIR, @@ -135,7 +135,7 @@ getTicketIndex(AccountID const& account, std::uint32_t ticketSeq) uint256 getTicketIndex(AccountID const& account, SeqProxy ticketSeq) { - assert(ticketSeq.isTicket()); + ASSERT(ticketSeq.isTicket(), "ripple::getTicketIndex : valid input"); return getTicketIndex(account, ticketSeq.value()); } @@ -222,7 +222,7 @@ line( // There is code in SetTrust that calls us with id0 == id1, to allow users // to locate and delete such "weird" trustlines. If we remove that code, we // could enable this assert: - // assert(id0 != id1); + // ASSERT(id0 != id1, "ripple::keylet::line : accounts must be different"); // A trust line is shared between two accounts; while we typically think // of this as an "issuer" and a "holder" the relationship is actually fully @@ -251,7 +251,7 @@ offer(AccountID const& id, std::uint32_t seq) noexcept Keylet quality(Keylet const& k, std::uint64_t q) noexcept { - assert(k.type == ltDIR_NODE); + ASSERT(k.type == ltDIR_NODE, "ripple::keylet::quality : valid input type"); // Indexes are stored in big endian format: they print as hex as stored. // Most significant bytes are first and the least significant bytes @@ -269,7 +269,9 @@ quality(Keylet const& k, std::uint64_t q) noexcept Keylet next_t::operator()(Keylet const& k) const { - assert(k.type == ltDIR_NODE); + ASSERT( + k.type == ltDIR_NODE, + "ripple::keylet::next_t::operator() : valid input type"); return {ltDIR_NODE, getQualityNext(k.key)}; } @@ -387,7 +389,8 @@ nftpage_max(AccountID const& owner) Keylet nftpage(Keylet const& k, uint256 const& token) { - assert(k.type == ltNFTOKEN_PAGE); + ASSERT( + k.type == ltNFTOKEN_PAGE, "ripple::keylet::nftpage : valid input type"); return {ltNFTOKEN_PAGE, (k.key & ~nft::pageMask) + (token & nft::pageMask)}; } diff --git a/src/libxrpl/protocol/Keylet.cpp b/src/libxrpl/protocol/Keylet.cpp index 23847811d3b..ab6b8ad0cf7 100644 --- a/src/libxrpl/protocol/Keylet.cpp +++ b/src/libxrpl/protocol/Keylet.cpp @@ -25,7 +25,9 @@ namespace ripple { bool Keylet::check(STLedgerEntry const& sle) const { - assert(sle.getType() != ltANY || sle.getType() != ltCHILD); + ASSERT( + sle.getType() != ltANY || sle.getType() != ltCHILD, + "ripple::Keylet::check : valid input type"); if (type == ltANY) return true; diff --git a/src/libxrpl/protocol/Quality.cpp b/src/libxrpl/protocol/Quality.cpp index c6464eba9d2..005e824760e 100644 --- a/src/libxrpl/protocol/Quality.cpp +++ b/src/libxrpl/protocol/Quality.cpp @@ -17,8 +17,8 @@ */ //============================================================================== +#include #include -#include #include namespace ripple { @@ -35,7 +35,7 @@ Quality::Quality(Amounts const& amount) Quality& Quality::operator++() { - assert(m_value > 0); + ASSERT(m_value > 0, "ripple::Quality::operator++() : minimum value"); --m_value; return *this; } @@ -51,7 +51,9 @@ Quality::operator++(int) Quality& Quality::operator--() { - assert(m_value < std::numeric_limits::max()); + ASSERT( + m_value < std::numeric_limits::max(), + "ripple::Quality::operator--() : maximum value"); ++m_value; return *this; } @@ -81,10 +83,11 @@ ceil_in_impl( // Clamp out if (result.out > amount.out) result.out = amount.out; - assert(result.in == limit); + ASSERT( + result.in == limit, "ripple::ceil_in_impl : result matches limit"); return result; } - assert(amount.in <= limit); + ASSERT(amount.in <= limit, "ripple::ceil_in_impl : result inside limit"); return amount; } @@ -120,10 +123,12 @@ ceil_out_impl( // Clamp in if (result.in > amount.in) result.in = amount.in; - assert(result.out == limit); + ASSERT( + result.out == limit, + "ripple::ceil_out_impl : result matches limit"); return result; } - assert(amount.out <= limit); + ASSERT(amount.out <= limit, "ripple::ceil_out_impl : result inside limit"); return amount; } @@ -146,17 +151,23 @@ Quality composed_quality(Quality const& lhs, Quality const& rhs) { STAmount const lhs_rate(lhs.rate()); - assert(lhs_rate != beast::zero); + ASSERT( + lhs_rate != beast::zero, + "ripple::composed_quality : nonzero left input"); STAmount const rhs_rate(rhs.rate()); - assert(rhs_rate != beast::zero); + ASSERT( + rhs_rate != beast::zero, + "ripple::composed_quality : nonzero right input"); STAmount const rate(mulRound(lhs_rate, rhs_rate, lhs_rate.asset(), true)); std::uint64_t const stored_exponent(rate.exponent() + 100); std::uint64_t const stored_mantissa(rate.mantissa()); - assert((stored_exponent > 0) && (stored_exponent <= 255)); + ASSERT( + (stored_exponent > 0) && (stored_exponent <= 255), + "ripple::composed_quality : valid exponent"); return Quality((stored_exponent << (64 - 8)) | stored_mantissa); } diff --git a/src/libxrpl/protocol/Rate2.cpp b/src/libxrpl/protocol/Rate2.cpp index 33bd9c5d0be..3e7d467e184 100644 --- a/src/libxrpl/protocol/Rate2.cpp +++ b/src/libxrpl/protocol/Rate2.cpp @@ -46,7 +46,7 @@ transferFeeAsRate(std::uint16_t fee) STAmount multiply(STAmount const& amount, Rate const& rate) { - assert(rate.value != 0); + ASSERT(rate.value != 0, "ripple::nft::multiply : nonzero rate input"); if (rate == parityRate) return amount; @@ -57,7 +57,7 @@ multiply(STAmount const& amount, Rate const& rate) STAmount multiplyRound(STAmount const& amount, Rate const& rate, bool roundUp) { - assert(rate.value != 0); + ASSERT(rate.value != 0, "ripple::nft::multiplyRound : nonzero rate input"); if (rate == parityRate) return amount; @@ -72,7 +72,9 @@ multiplyRound( Asset const& asset, bool roundUp) { - assert(rate.value != 0); + ASSERT( + rate.value != 0, + "ripple::nft::multiplyRound(Issue) : nonzero rate input"); if (rate == parityRate) { @@ -85,7 +87,7 @@ multiplyRound( STAmount divide(STAmount const& amount, Rate const& rate) { - assert(rate.value != 0); + ASSERT(rate.value != 0, "ripple::nft::divide : nonzero rate input"); if (rate == parityRate) return amount; @@ -96,7 +98,7 @@ divide(STAmount const& amount, Rate const& rate) STAmount divideRound(STAmount const& amount, Rate const& rate, bool roundUp) { - assert(rate.value != 0); + ASSERT(rate.value != 0, "ripple::nft::divideRound : nonzero rate input"); if (rate == parityRate) return amount; @@ -111,7 +113,9 @@ divideRound( Asset const& asset, bool roundUp) { - assert(rate.value != 0); + ASSERT( + rate.value != 0, + "ripple::nft::divideRound(Issue) : nonzero rate input"); if (rate == parityRate) return amount; diff --git a/src/libxrpl/protocol/Rules.cpp b/src/libxrpl/protocol/Rules.cpp index f47e966e138..3edc1448d00 100644 --- a/src/libxrpl/protocol/Rules.cpp +++ b/src/libxrpl/protocol/Rules.cpp @@ -91,7 +91,10 @@ class Rules::Impl return true; if (!digest_ || !other.digest_) return false; - assert(presets_ == other.presets_); + ASSERT( + presets_ == other.presets_, + "ripple::Rules::Impl::operator==(Impl) const : input presets do " + "match"); return *digest_ == *other.digest_; } }; @@ -118,7 +121,7 @@ Rules::presets() const bool Rules::enabled(uint256 const& feature) const { - assert(impl_); + ASSERT(impl_ != nullptr, "ripple::Rules::enabled : initialized"); // The functionality of the "NonFungibleTokensV1_1" amendment is // precisely the functionality of the following three amendments @@ -137,7 +140,9 @@ Rules::enabled(uint256 const& feature) const bool Rules::operator==(Rules const& other) const { - assert(impl_ && other.impl_); + ASSERT( + impl_ && other.impl_, + "ripple::Rules::operator==(Rules) const : both initialized"); if (impl_.get() == other.impl_.get()) return true; return *impl_ == *other.impl_; diff --git a/src/libxrpl/protocol/SField.cpp b/src/libxrpl/protocol/SField.cpp index 537fa557fcc..20e1e112655 100644 --- a/src/libxrpl/protocol/SField.cpp +++ b/src/libxrpl/protocol/SField.cpp @@ -17,8 +17,8 @@ */ //============================================================================== +#include #include -#include #include #include #include diff --git a/src/libxrpl/protocol/STAccount.cpp b/src/libxrpl/protocol/STAccount.cpp index 8ae43f76863..d3d93f75601 100644 --- a/src/libxrpl/protocol/STAccount.cpp +++ b/src/libxrpl/protocol/STAccount.cpp @@ -80,8 +80,10 @@ STAccount::getSType() const void STAccount::add(Serializer& s) const { - assert(getFName().isBinary()); - assert(getFName().fieldType == STI_ACCOUNT); + ASSERT(getFName().isBinary(), "ripple::STAccount::add : field is binary"); + ASSERT( + getFName().fieldType == STI_ACCOUNT, + "ripple::STAccount::add : valid field type"); // Preserve the serialization behavior of an STBlob: // o If we are default (all zeros) serialize as an empty blob. diff --git a/src/libxrpl/protocol/STAmount.cpp b/src/libxrpl/protocol/STAmount.cpp index fe13118d88c..c33b2b40aa3 100644 --- a/src/libxrpl/protocol/STAmount.cpp +++ b/src/libxrpl/protocol/STAmount.cpp @@ -29,7 +29,7 @@ #include #include #include -#include + #include #include @@ -68,11 +68,13 @@ getInt64Value(STAmount const& amount, bool valid, const char* error) { if (!valid) Throw(error); - assert(amount.exponent() == 0); + ASSERT(amount.exponent() == 0, "ripple::getInt64Value : exponent is zero"); auto ret = static_cast(amount.mantissa()); - assert(static_cast(ret) == amount.mantissa()); + ASSERT( + static_cast(ret) == amount.mantissa(), + "ripple::getInt64Value : mantissa must roundtrip"); if (amount.negative()) ret = -ret; @@ -199,7 +201,10 @@ STAmount::STAmount(SField const& name, std::uint64_t mantissa, bool negative) , mOffset(0) , mIsNegative(negative) { - assert(mValue <= std::numeric_limits::max()); + ASSERT( + mValue <= std::numeric_limits::max(), + "ripple::STAmount::STAmount(SField, std::uint64_t, bool) : maximum " + "mantissa input"); } STAmount::STAmount(SField const& name, STAmount const& from) @@ -209,7 +214,9 @@ STAmount::STAmount(SField const& name, STAmount const& from) , mOffset(from.mOffset) , mIsNegative(from.mIsNegative) { - assert(mValue <= std::numeric_limits::max()); + ASSERT( + mValue <= std::numeric_limits::max(), + "ripple::STAmount::STAmount(SField, STAmount) : maximum input"); canonicalize(); } @@ -221,7 +228,10 @@ STAmount::STAmount(std::uint64_t mantissa, bool negative) , mOffset(0) , mIsNegative(mantissa != 0 && negative) { - assert(mValue <= std::numeric_limits::max()); + ASSERT( + mValue <= std::numeric_limits::max(), + "ripple::STAmount::STAmount(std::uint64_t, bool) : maximum mantissa " + "input"); } STAmount::STAmount(XRPAmount const& amount) @@ -305,7 +315,9 @@ STAmount::mpt() const STAmount& STAmount::operator=(IOUAmount const& iou) { - assert(native() == false); + ASSERT( + native() == false, + "ripple::STAmount::operator=(IOUAmount) : is not XRP"); mOffset = iou.exponent(); mIsNegative = iou < beast::zero; if (mIsNegative) @@ -444,7 +456,9 @@ getRate(STAmount const& offerOut, STAmount const& offerIn) STAmount r = divide(offerIn, offerOut, noIssue()); if (r == beast::zero) // offer is too good return 0; - assert((r.exponent() >= -100) && (r.exponent() <= 155)); + ASSERT( + (r.exponent() >= -100) && (r.exponent() <= 155), + "ripple::getRate : exponent inside range"); std::uint64_t ret = r.exponent() + 100; return (ret << (64 - 8)) | r.mantissa(); } @@ -525,7 +539,7 @@ STAmount::getText() const return ret; } - assert(mOffset + 43 > 0); + ASSERT(mOffset + 43 > 0, "ripple::STAmount::getText : minimum offset"); size_t const pad_prefix = 27; size_t const pad_suffix = 23; @@ -549,7 +563,9 @@ STAmount::getText() const if (std::distance(pre_from, pre_to) > pad_prefix) pre_from += pad_prefix; - assert(post_to >= post_from); + ASSERT( + post_to >= post_from, + "ripple::STAmount::getText : first distance check"); pre_from = std::find_if(pre_from, pre_to, [](char c) { return c != '0'; }); @@ -558,7 +574,9 @@ STAmount::getText() const if (std::distance(post_from, post_to) > pad_suffix) post_to -= pad_suffix; - assert(post_to >= post_from); + ASSERT( + post_to >= post_from, + "ripple::STAmount::getText : second distance check"); post_to = std::find_if( std::make_reverse_iterator(post_to), @@ -594,7 +612,7 @@ STAmount::add(Serializer& s) const { if (native()) { - assert(mOffset == 0); + ASSERT(mOffset == 0, "ripple::STAmount::add : zero offset"); if (!mIsNegative) s.add64(mValue | cPositive); @@ -771,10 +789,15 @@ STAmount::canonicalize() if (mOffset > cMaxOffset) Throw("value overflow"); - assert((mValue == 0) || ((mValue >= cMinValue) && (mValue <= cMaxValue))); - assert( - (mValue == 0) || ((mOffset >= cMinOffset) && (mOffset <= cMaxOffset))); - assert((mValue != 0) || (mOffset != -100)); + ASSERT( + (mValue == 0) || ((mValue >= cMinValue) && (mValue <= cMaxValue)), + "ripple::STAmount::canonicalize : value inside range"); + ASSERT( + (mValue == 0) || ((mOffset >= cMinOffset) && (mOffset <= cMaxOffset)), + "ripple::STAmount::canonicalize : offset inside range"); + ASSERT( + (mValue != 0) || (mOffset != -100), + "ripple::STAmount::canonicalize : value or offset set"); } void diff --git a/src/libxrpl/protocol/STBase.cpp b/src/libxrpl/protocol/STBase.cpp index 73565cbf765..d93068bb053 100644 --- a/src/libxrpl/protocol/STBase.cpp +++ b/src/libxrpl/protocol/STBase.cpp @@ -17,10 +17,9 @@ */ //============================================================================== +#include #include #include -#include -#include namespace ripple { @@ -30,7 +29,7 @@ STBase::STBase() : fName(&sfGeneric) STBase::STBase(SField const& n) : fName(&n) { - assert(fName); + ASSERT(fName != nullptr, "ripple::STBase::STBase : field is set"); } STBase& @@ -106,13 +105,15 @@ void STBase::add(Serializer& s) const { // Should never be called - assert(false); + UNREACHABLE("ripple::STBase::add : not implemented"); } bool STBase::isEquivalent(const STBase& t) const { - assert(getSType() == STI_NOTPRESENT); + ASSERT( + getSType() == STI_NOTPRESENT, + "ripple::STBase::isEquivalent : type not present"); return t.getSType() == STI_NOTPRESENT; } @@ -126,7 +127,7 @@ void STBase::setFName(SField const& n) { fName = &n; - assert(fName); + ASSERT(fName != nullptr, "ripple::STBase::setFName : field is set"); } SField const& @@ -138,7 +139,7 @@ STBase::getFName() const void STBase::addFieldID(Serializer& s) const { - assert(fName->isBinary()); + ASSERT(fName->isBinary(), "ripple::STBase::addFieldID : field is binary"); s.addFieldID(fName->fieldType, fName->fieldValue); } diff --git a/src/libxrpl/protocol/STBlob.cpp b/src/libxrpl/protocol/STBlob.cpp index 63e7b4bf3da..755588138a2 100644 --- a/src/libxrpl/protocol/STBlob.cpp +++ b/src/libxrpl/protocol/STBlob.cpp @@ -54,10 +54,11 @@ STBlob::getText() const void STBlob::add(Serializer& s) const { - assert(getFName().isBinary()); - assert( + ASSERT(getFName().isBinary(), "ripple::STBlob::add : field is binary"); + ASSERT( (getFName().fieldType == STI_VL) || - (getFName().fieldType == STI_ACCOUNT)); + (getFName().fieldType == STI_ACCOUNT), + "ripple::STBlob::add : valid field type"); s.addVL(value_.data(), value_.size()); } diff --git a/src/libxrpl/protocol/STInteger.cpp b/src/libxrpl/protocol/STInteger.cpp index 7dfcc50dea0..5e8fc47d9da 100644 --- a/src/libxrpl/protocol/STInteger.cpp +++ b/src/libxrpl/protocol/STInteger.cpp @@ -199,12 +199,16 @@ Json::Value STUInt64::getJson(JsonOptions) const { auto convertToString = [](uint64_t const value, int const base) { - assert(base == 10 || base == 16); + ASSERT( + base == 10 || base == 16, + "ripple::STUInt64::getJson : base 10 or 16"); std::string str( base == 10 ? 20 : 16, 0); // Allocate space depending on base auto ret = std::to_chars(str.data(), str.data() + str.size(), value, base); - assert(ret.ec == std::errc()); + ASSERT( + ret.ec == std::errc(), + "ripple::STUInt64::getJson : to_chars succeeded"); str.resize(std::distance(str.data(), ret.ptr)); return str; }; diff --git a/src/libxrpl/protocol/STLedgerEntry.cpp b/src/libxrpl/protocol/STLedgerEntry.cpp index 1801149ab2a..b7579a04ca8 100644 --- a/src/libxrpl/protocol/STLedgerEntry.cpp +++ b/src/libxrpl/protocol/STLedgerEntry.cpp @@ -161,7 +161,9 @@ STLedgerEntry::thread( if (oldPrevTxID == txID) { // this transaction is already threaded - assert(getFieldU32(sfPreviousTxnLgrSeq) == ledgerSeq); + ASSERT( + getFieldU32(sfPreviousTxnLgrSeq) == ledgerSeq, + "ripple::STLedgerEntry::thread : ledger sequence match"); return false; } diff --git a/src/libxrpl/protocol/STNumber.cpp b/src/libxrpl/protocol/STNumber.cpp index 3a92bbb02f9..74bda0046cf 100644 --- a/src/libxrpl/protocol/STNumber.cpp +++ b/src/libxrpl/protocol/STNumber.cpp @@ -19,6 +19,7 @@ #include +#include #include namespace ripple { @@ -52,8 +53,10 @@ STNumber::getText() const void STNumber::add(Serializer& s) const { - assert(getFName().isBinary()); - assert(getFName().fieldType == getSType()); + ASSERT(getFName().isBinary(), "ripple::STNumber::add : field is binary"); + ASSERT( + getFName().fieldType == getSType(), + "ripple::STNumber::add : field type match"); s.add64(value_.mantissa()); s.add32(value_.exponent()); } @@ -85,7 +88,9 @@ STNumber::move(std::size_t n, void* buf) bool STNumber::isEquivalent(STBase const& t) const { - assert(t.getSType() == this->getSType()); + ASSERT( + t.getSType() == this->getSType(), + "ripple::STNumber::isEquivalent : field type match"); STNumber const& v = dynamic_cast(t); return value_ == v; } diff --git a/src/libxrpl/protocol/STObject.cpp b/src/libxrpl/protocol/STObject.cpp index c8fc88348e9..520dc53b0de 100644 --- a/src/libxrpl/protocol/STObject.cpp +++ b/src/libxrpl/protocol/STObject.cpp @@ -862,9 +862,10 @@ STObject::add(Serializer& s, WhichFields whichFields) const // the type associated by rule with this field name // must be OBJECT, or the object cannot be deserialized SerializedTypeID const sType{field->getSType()}; - assert( + ASSERT( (sType != STI_OBJECT) || - (field->getFName().fieldType == STI_OBJECT)); + (field->getFName().fieldType == STI_OBJECT), + "ripple::STObject::add : valid field type"); field->addFieldID(s); field->add(s); if (sType == STI_ARRAY || sType == STI_OBJECT) diff --git a/src/libxrpl/protocol/STParsedJSON.cpp b/src/libxrpl/protocol/STParsedJSON.cpp index 09b6b6679d7..7d08993a8ba 100644 --- a/src/libxrpl/protocol/STParsedJSON.cpp +++ b/src/libxrpl/protocol/STParsedJSON.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -41,7 +42,6 @@ #include #include -#include #include #include diff --git a/src/libxrpl/protocol/STPathSet.cpp b/src/libxrpl/protocol/STPathSet.cpp index 78c47cadc66..3409299d7cb 100644 --- a/src/libxrpl/protocol/STPathSet.cpp +++ b/src/libxrpl/protocol/STPathSet.cpp @@ -209,8 +209,10 @@ STPathSet::getSType() const void STPathSet::add(Serializer& s) const { - assert(getFName().isBinary()); - assert(getFName().fieldType == STI_PATHSET); + ASSERT(getFName().isBinary(), "ripple::STPathSet::add : field is binary"); + ASSERT( + getFName().fieldType == STI_PATHSET, + "ripple::STPathSet::add : valid field type"); bool first = true; for (auto const& spPath : value) diff --git a/src/libxrpl/protocol/STTx.cpp b/src/libxrpl/protocol/STTx.cpp index 7bd25246c53..b530271080d 100644 --- a/src/libxrpl/protocol/STTx.cpp +++ b/src/libxrpl/protocol/STTx.cpp @@ -137,7 +137,9 @@ STTx::getMentionedAccounts() const { if (auto sacc = dynamic_cast(&it)) { - assert(!sacc->isDefault()); + ASSERT( + !sacc->isDefault(), + "ripple::STTx::getMentionedAccounts : account is set"); if (!sacc->isDefault()) list.insert(sacc->value()); } @@ -298,7 +300,8 @@ STTx::getMetaSQL( std::string rTxn = sqlBlobLiteral(rawTxn.peekData()); auto format = TxFormats::getInstance().findByType(tx_type_); - assert(format != nullptr); + ASSERT( + format != nullptr, "ripple::STTx::getMetaSQL : non-null type format"); return str( boost::format(bfTrans) % to_string(getTransactionID()) % diff --git a/src/libxrpl/protocol/STValidation.cpp b/src/libxrpl/protocol/STValidation.cpp index ca5ceb0d9ce..5820fc9f9b0 100644 --- a/src/libxrpl/protocol/STValidation.cpp +++ b/src/libxrpl/protocol/STValidation.cpp @@ -107,7 +107,9 @@ STValidation::isValid() const noexcept { if (!valid_) { - assert(publicKeyType(getSignerPublic()) == KeyType::secp256k1); + ASSERT( + publicKeyType(getSignerPublic()) == KeyType::secp256k1, + "ripple::STValidation::isValid : valid key type"); valid_ = verifyDigest( getSignerPublic(), diff --git a/src/libxrpl/protocol/STVar.cpp b/src/libxrpl/protocol/STVar.cpp index 55927cb33aa..4c9217328f6 100644 --- a/src/libxrpl/protocol/STVar.cpp +++ b/src/libxrpl/protocol/STVar.cpp @@ -121,7 +121,9 @@ STVar::STVar(SerialIter& sit, SField const& name, int depth) STVar::STVar(SerializedTypeID id, SField const& name) { - assert((id == STI_NOTPRESENT) || (id == name.fieldType)); + ASSERT( + (id == STI_NOTPRESENT) || (id == name.fieldType), + "ripple::detail::STVar::STVar(SerializedTypeID) : valid type input"); constructST(id, 0, name); } diff --git a/src/libxrpl/protocol/STVector256.cpp b/src/libxrpl/protocol/STVector256.cpp index 385c0ef76db..e9ea1e862de 100644 --- a/src/libxrpl/protocol/STVector256.cpp +++ b/src/libxrpl/protocol/STVector256.cpp @@ -68,8 +68,10 @@ STVector256::isDefault() const void STVector256::add(Serializer& s) const { - assert(getFName().isBinary()); - assert(getFName().fieldType == STI_VECTOR256); + ASSERT(getFName().isBinary(), "ripple::STVector256::add : field is binary"); + ASSERT( + getFName().fieldType == STI_VECTOR256, + "ripple::STVector256::add : valid field type"); s.addVL(mValue.begin(), mValue.end(), mValue.size() * (256 / 8)); } diff --git a/src/libxrpl/protocol/Serializer.cpp b/src/libxrpl/protocol/Serializer.cpp index ceaf76faf34..51fb94054e3 100644 --- a/src/libxrpl/protocol/Serializer.cpp +++ b/src/libxrpl/protocol/Serializer.cpp @@ -107,7 +107,9 @@ int Serializer::addFieldID(int type, int name) { int ret = mData.size(); - assert((type > 0) && (type < 256) && (name > 0) && (name < 256)); + ASSERT( + (type > 0) && (type < 256) && (name > 0) && (name < 256), + "ripple::Serializer::addFieldID : inputs inside range"); if (type < 16) { @@ -176,9 +178,10 @@ Serializer::addVL(Blob const& vector) { int ret = addEncoded(vector.size()); addRaw(vector); - assert( + ASSERT( mData.size() == - (ret + vector.size() + encodeLengthLength(vector.size()))); + (ret + vector.size() + encodeLengthLength(vector.size())), + "ripple::Serializer::addVL : size matches expected"); return ret; } @@ -482,7 +485,8 @@ SerialIter::getVLDataLength() } else { - assert(lenLen == 3); + ASSERT( + lenLen == 3, "ripple::SerialIter::getVLDataLength : lenLen is 3"); int b2 = get8(); int b3 = get8(); datLen = Serializer::decodeVLLength(b1, b2, b3); diff --git a/src/libxrpl/protocol/TxMeta.cpp b/src/libxrpl/protocol/TxMeta.cpp index 253d00e8414..ea3e43240ba 100644 --- a/src/libxrpl/protocol/TxMeta.cpp +++ b/src/libxrpl/protocol/TxMeta.cpp @@ -55,7 +55,9 @@ TxMeta::TxMeta(uint256 const& txid, std::uint32_t ledger, STObject const& obj) auto affectedNodes = dynamic_cast(obj.peekAtPField(sfAffectedNodes)); - assert(affectedNodes); + ASSERT( + affectedNodes != nullptr, + "ripple::TxMeta::TxMeta(STObject) : type cast succeeded"); if (affectedNodes) mNodes = *affectedNodes; @@ -106,7 +108,9 @@ TxMeta::setAffectedNode( mNodes.push_back(STObject(type)); STObject& obj = mNodes.back(); - assert(obj.getFName() == type); + ASSERT( + obj.getFName() == type, + "ripple::TxMeta::setAffectedNode : field type match"); obj.setFieldH256(sfLedgerIndex, node); obj.setFieldU16(sfLedgerEntryType, nodeType); } @@ -127,14 +131,18 @@ TxMeta::getAffectedAccounts() const if (index != -1) { auto inner = dynamic_cast(&it.peekAtIndex(index)); - assert(inner); + ASSERT( + inner != nullptr, + "ripple::getAffectedAccounts : STObject type cast succeeded"); if (inner) { for (auto const& field : *inner) { if (auto sa = dynamic_cast(&field)) { - assert(!sa->isDefault()); + ASSERT( + !sa->isDefault(), + "ripple::getAffectedAccounts : account is set"); if (!sa->isDefault()) list.insert(sa->value()); } @@ -145,7 +153,10 @@ TxMeta::getAffectedAccounts() const (field.getFName() == sfTakerGets)) { auto lim = dynamic_cast(&field); - assert(lim); + ASSERT( + lim != nullptr, + "ripple::getAffectedAccounts : STAmount type cast " + "succeeded"); if (lim != nullptr) { @@ -175,7 +186,9 @@ TxMeta::getAffectedNode(SLE::ref node, SField const& type) mNodes.push_back(STObject(type)); STObject& obj = mNodes.back(); - assert(obj.getFName() == type); + ASSERT( + obj.getFName() == type, + "ripple::TxMeta::getAffectedNode(SLE::ref) : field type match"); obj.setFieldH256(sfLedgerIndex, index); obj.setFieldU16(sfLedgerEntryType, node->getFieldU16(sfLedgerEntryType)); @@ -190,7 +203,7 @@ TxMeta::getAffectedNode(uint256 const& node) if (n.getFieldH256(sfLedgerIndex) == node) return n; } - assert(false); + UNREACHABLE("ripple::TxMeta::getAffectedNode(uint256) : node not found"); Throw("Affected node not found"); return *(mNodes.begin()); // Silence compiler warning. } @@ -199,7 +212,7 @@ STObject TxMeta::getAsObject() const { STObject metaData(sfTransactionMetaData); - assert(mResult != 255); + ASSERT(mResult != 255, "ripple::TxMeta::getAsObject : result is set"); metaData.setFieldU8(sfTransactionResult, mResult); metaData.setFieldU32(sfTransactionIndex, mIndex); metaData.emplace_back(mNodes); @@ -213,7 +226,9 @@ TxMeta::addRaw(Serializer& s, TER result, std::uint32_t index) { mResult = TERtoInt(result); mIndex = index; - assert((mResult == 0) || ((mResult > 100) && (mResult <= 255))); + ASSERT( + (mResult == 0) || ((mResult > 100) && (mResult <= 255)), + "ripple::TxMeta::addRaw : valid TER input"); mNodes.sort([](STObject const& o1, STObject const& o2) { return o1.getFieldH256(sfLedgerIndex) < o2.getFieldH256(sfLedgerIndex); diff --git a/src/libxrpl/protocol/tokens.cpp b/src/libxrpl/protocol/tokens.cpp index ccae1fb8ed2..de3812637cf 100644 --- a/src/libxrpl/protocol/tokens.cpp +++ b/src/libxrpl/protocol/tokens.cpp @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -35,7 +36,6 @@ #include #include -#include #include #include #include @@ -248,7 +248,8 @@ encodeBase58( iter[-1] = carry % 58; carry /= 58; } - assert(carry == 0); + ASSERT( + carry == 0, "ripple::b58_ref::detail::encodeBase58 : zero carry"); pbegin++; } @@ -298,7 +299,8 @@ decodeBase58(std::string const& s) *iter = carry % 256; carry /= 256; } - assert(carry == 0); + ASSERT( + carry == 0, "ripple::b58_ref::detail::decodeBase58 : zero carry"); ++psz; --remain; } @@ -535,7 +537,9 @@ b58_to_b256_be(std::string_view input, std::span out) ripple::b58_fast::detail::div_rem(input.size(), 10); auto const num_partial_coeffs = partial_coeff_len ? 1 : 0; auto const num_b_58_10_coeffs = num_full_coeffs + num_partial_coeffs; - assert(num_b_58_10_coeffs <= b_58_10_coeff.size()); + ASSERT( + num_b_58_10_coeffs <= b_58_10_coeff.size(), + "ripple::b58_fast::detail::b58_to_b256_be : maximum coeff"); for (auto c : input.substr(0, partial_coeff_len)) { auto cur_val = ::ripple::alphabetReverse[c]; diff --git a/src/libxrpl/resource/Consumer.cpp b/src/libxrpl/resource/Consumer.cpp index b8652546841..adabd770964 100644 --- a/src/libxrpl/resource/Consumer.cpp +++ b/src/libxrpl/resource/Consumer.cpp @@ -17,10 +17,10 @@ */ //============================================================================== +#include #include #include #include -#include namespace ripple { namespace Resource { @@ -109,14 +109,18 @@ Consumer::charge(Charge const& what) bool Consumer::warn() { - assert(m_entry != nullptr); + ASSERT( + m_entry != nullptr, + "ripple::Resource::Consumer::warn : non-null entry"); return m_logic->warn(*m_entry); } bool Consumer::disconnect(beast::Journal const& j) { - assert(m_entry != nullptr); + ASSERT( + m_entry != nullptr, + "ripple::Resource::Consumer::disconnect : non-null entry"); bool const d = m_logic->disconnect(*m_entry); if (d) { @@ -128,14 +132,18 @@ Consumer::disconnect(beast::Journal const& j) int Consumer::balance() { - assert(m_entry != nullptr); + ASSERT( + m_entry != nullptr, + "ripple::Resource::Consumer::balance : non-null entry"); return m_logic->balance(*m_entry); } Entry& Consumer::entry() { - assert(m_entry != nullptr); + ASSERT( + m_entry != nullptr, + "ripple::Resource::Consumer::entry : non-null entry"); return *m_entry; } diff --git a/src/test/jtx/impl/amount.cpp b/src/test/jtx/impl/amount.cpp index 9f374c2cb58..5be53dc0a95 100644 --- a/src/test/jtx/impl/amount.cpp +++ b/src/test/jtx/impl/amount.cpp @@ -20,7 +20,6 @@ #include #include #include -#include #include #include diff --git a/src/test/overlay/short_read_test.cpp b/src/test/overlay/short_read_test.cpp index 6dd4f8c00b8..0efc49b84e3 100644 --- a/src/test/overlay/short_read_test.cpp +++ b/src/test/overlay/short_read_test.cpp @@ -26,7 +26,6 @@ #include #include -#include #include #include #include diff --git a/src/xrpld/app/consensus/RCLConsensus.cpp b/src/xrpld/app/consensus/RCLConsensus.cpp index 263d660d003..0be77c7de79 100644 --- a/src/xrpld/app/consensus/RCLConsensus.cpp +++ b/src/xrpld/app/consensus/RCLConsensus.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -92,7 +93,9 @@ RCLConsensus::Adaptor::Adaptor( std::numeric_limits::max() - 1)) , nUnlVote_(validatorKeys_.nodeID, j_) { - assert(valCookie_ != 0); + ASSERT( + valCookie_ != 0, + "ripple::RCLConsensus::Adaptor::Adaptor : nonzero cookie"); JLOG(j_.info()) << "Consensus engine started (cookie: " + std::to_string(valCookie_) + ")"; @@ -146,8 +149,12 @@ RCLConsensus::Adaptor::acquireLedger(LedgerHash const& hash) return std::nullopt; } - assert(!built->open() && built->isImmutable()); - assert(built->info().hash == hash); + ASSERT( + !built->open() && built->isImmutable(), + "ripple::RCLConsensus::Adaptor::acquireLedger : valid ledger state"); + ASSERT( + built->info().hash == hash, + "ripple::RCLConsensus::Adaptor::acquireLedger : ledger hash match"); // Notify inbound transactions of the new ledger sequence number inboundTransactions_.newRound(built->info().seq); @@ -673,8 +680,12 @@ RCLConsensus::Adaptor::doAccept( ledgerMaster_.switchLCL(built.ledger_); // Do these need to exist? - assert(ledgerMaster_.getClosedLedger()->info().hash == built.id()); - assert(app_.openLedger().current()->info().parentHash == built.id()); + ASSERT( + ledgerMaster_.getClosedLedger()->info().hash == built.id(), + "ripple::RCLConsensus::Adaptor::doAccept : ledger hash match"); + ASSERT( + app_.openLedger().current()->info().parentHash == built.id(), + "ripple::RCLConsensus::Adaptor::doAccept : parent hash match"); } //------------------------------------------------------------------------- @@ -770,7 +781,9 @@ RCLConsensus::Adaptor::buildLCL( std::shared_ptr built = [&]() { if (auto const replayData = ledgerMaster_.releaseReplay()) { - assert(replayData->parent()->info().hash == previousLedger.id()); + ASSERT( + replayData->parent()->info().hash == previousLedger.id(), + "ripple::RCLConsensus::Adaptor::buildLCL : parent hash match"); return buildLedger(*replayData, tapNONE, app_, j_); } return buildLedger( diff --git a/src/xrpld/app/consensus/RCLCxPeerPos.cpp b/src/xrpld/app/consensus/RCLCxPeerPos.cpp index 74747853a2d..14a60a84182 100644 --- a/src/xrpld/app/consensus/RCLCxPeerPos.cpp +++ b/src/xrpld/app/consensus/RCLCxPeerPos.cpp @@ -38,7 +38,9 @@ RCLCxPeerPos::RCLCxPeerPos( { // The maximum allowed size of a signature is 72 bytes; we verify // this elsewhere, but we want to be extra careful here: - assert(signature.size() != 0 && signature.size() <= signature_.capacity()); + ASSERT( + signature.size() != 0 && signature.size() <= signature_.capacity(), + "ripple::RCLCxPeerPos::RCLCxPeerPos : valid signature size"); if (signature.size() != 0 && signature.size() <= signature_.capacity()) signature_.assign(signature.begin(), signature.end()); diff --git a/src/xrpld/app/consensus/RCLCxTx.h b/src/xrpld/app/consensus/RCLCxTx.h index 58e58ac3b7d..0181eb03c21 100644 --- a/src/xrpld/app/consensus/RCLCxTx.h +++ b/src/xrpld/app/consensus/RCLCxTx.h @@ -111,7 +111,9 @@ class RCLTxSet */ RCLTxSet(std::shared_ptr m) : map_{std::move(m)} { - assert(map_); + ASSERT( + map_ != nullptr, + "ripple::RCLTxSet::MutableTxSet::RCLTxSet : non-null input"); } /** Constructor from a previously created MutableTxSet @@ -177,7 +179,9 @@ class RCLTxSet std::map ret; for (auto const& [k, v] : delta) { - assert((v.first && !v.second) || (v.second && !v.first)); + ASSERT( + (v.first && !v.second) || (v.second && !v.first), + "ripple::RCLTxSet::compare : either side is set"); ret[k] = static_cast(v.first); } diff --git a/src/xrpld/app/consensus/RCLValidations.cpp b/src/xrpld/app/consensus/RCLValidations.cpp index 096ec56df6f..e620cd3de90 100644 --- a/src/xrpld/app/consensus/RCLValidations.cpp +++ b/src/xrpld/app/consensus/RCLValidations.cpp @@ -50,7 +50,10 @@ RCLValidatedLedger::RCLValidatedLedger( auto const hashIndex = ledger->read(keylet::skip()); if (hashIndex) { - assert(hashIndex->getFieldU32(sfLastLedgerSequence) == (seq() - 1)); + ASSERT( + hashIndex->getFieldU32(sfLastLedgerSequence) == (seq() - 1), + "ripple::RCLValidatedLedger::RCLValidatedLedger(Ledger) : valid " + "last ledger sequence"); ancestors_ = hashIndex->getFieldV256(sfHashes).value(); } else @@ -151,8 +154,12 @@ RCLValidationsAdaptor::acquire(LedgerHash const& hash) return std::nullopt; } - assert(!ledger->open() && ledger->isImmutable()); - assert(ledger->info().hash == hash); + ASSERT( + !ledger->open() && ledger->isImmutable(), + "ripple::RCLValidationsAdaptor::acquire : valid ledger state"); + ASSERT( + ledger->info().hash == hash, + "ripple::RCLValidationsAdaptor::acquire : ledger hash match"); return RCLValidatedLedger(std::move(ledger), j_); } @@ -191,7 +198,9 @@ handleNewValidation( { if (bypassAccept == BypassAccept::yes) { - assert(j.has_value()); + ASSERT( + j.has_value(), + "ripple::handleNewValidation : journal is available"); if (j.has_value()) { JLOG(j->trace()) << "Bypassing checkAccept for validation " diff --git a/src/xrpld/app/ledger/AcceptedLedgerTx.cpp b/src/xrpld/app/ledger/AcceptedLedgerTx.cpp index e1ad68dff37..620ab031762 100644 --- a/src/xrpld/app/ledger/AcceptedLedgerTx.cpp +++ b/src/xrpld/app/ledger/AcceptedLedgerTx.cpp @@ -33,7 +33,9 @@ AcceptedLedgerTx::AcceptedLedgerTx( , mMeta(txn->getTransactionID(), ledger->seq(), *met) , mAffected(mMeta.getAffectedAccounts()) { - assert(!ledger->open()); + ASSERT( + !ledger->open(), + "ripple::AcceptedLedgerTx::AcceptedLedgerTx : valid ledger state"); Serializer s; met->add(s); @@ -76,7 +78,9 @@ AcceptedLedgerTx::AcceptedLedgerTx( std::string AcceptedLedgerTx::getEscMeta() const { - assert(!mRawMeta.empty()); + ASSERT( + !mRawMeta.empty(), + "ripple::AcceptedLedgerTx::getEscMeta : metadata is set"); return sqlBlobLiteral(mRawMeta); } diff --git a/src/xrpld/app/ledger/ConsensusTransSetSF.cpp b/src/xrpld/app/ledger/ConsensusTransSetSF.cpp index 4aed7d94bf3..334b6d46dbd 100644 --- a/src/xrpld/app/ledger/ConsensusTransSetSF.cpp +++ b/src/xrpld/app/ledger/ConsensusTransSetSF.cpp @@ -60,7 +60,10 @@ ConsensusTransSetSF::gotNode( Serializer s(nodeData.data() + 4, nodeData.size() - 4); SerialIter sit(s.slice()); auto stx = std::make_shared(std::ref(sit)); - assert(stx->getTransactionID() == nodeHash.as_uint256()); + ASSERT( + stx->getTransactionID() == nodeHash.as_uint256(), + "ripple::ConsensusTransSetSF::gotNode : transaction hash " + "match"); auto const pap = &app_; app_.getJobQueue().addJob(jtTRANSACTION, "TXS->TXN", [pap, stx]() { pap->getOPs().submitTransaction(stx); @@ -92,7 +95,9 @@ ConsensusTransSetSF::getNode(SHAMapHash const& nodeHash) const Serializer s; s.add32(HashPrefix::transactionID); txn->getSTransaction()->add(s); - assert(sha512Half(s.slice()) == nodeHash.as_uint256()); + ASSERT( + sha512Half(s.slice()) == nodeHash.as_uint256(), + "ripple::ConsensusTransSetSF::getNode : transaction hash match"); nodeData = s.peekData(); return nodeData; } diff --git a/src/xrpld/app/ledger/Ledger.cpp b/src/xrpld/app/ledger/Ledger.cpp index 4991b551cd1..5fdc4811051 100644 --- a/src/xrpld/app/ledger/Ledger.cpp +++ b/src/xrpld/app/ledger/Ledger.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -49,7 +50,6 @@ #include #include #include -#include #include #include @@ -369,7 +369,7 @@ Ledger::setAccepted( bool correctCloseTime) { // Used when we witnessed the consensus. - assert(!open()); + ASSERT(!open(), "ripple::Ledger::setAccepted : valid ledger state"); info_.closeTime = closeTime; info_.closeTimeResolution = closeResolution; @@ -442,7 +442,7 @@ Ledger::read(Keylet const& k) const { if (k.key == beast::zero) { - assert(false); + UNREACHABLE("ripple::Ledger::read : zero key"); return nullptr; } auto const& item = stateMap_.peekItem(k.key); @@ -562,7 +562,9 @@ Ledger::rawTxInsert( std::shared_ptr const& txn, std::shared_ptr const& metaData) { - assert(metaData); + ASSERT( + metaData != nullptr, + "ripple::Ledger::rawTxInsert : non-null metadata input"); // low-level - just add to table Serializer s(txn->getDataLength() + metaData->getDataLength() + 16); @@ -579,7 +581,9 @@ Ledger::rawTxInsertWithHash( std::shared_ptr const& txn, std::shared_ptr const& metaData) { - assert(metaData); + ASSERT( + metaData != nullptr, + "ripple::Ledger::rawTxInsertWithHash : non-null metadata input"); // low-level - just add to table Serializer s(txn->getDataLength() + metaData->getDataLength() + 16); @@ -675,7 +679,9 @@ Ledger::setup() void Ledger::defaultFees(Config const& config) { - assert(fees_.base == 0 && fees_.reserve == 0 && fees_.increment == 0); + ASSERT( + fees_.base == 0 && fees_.reserve == 0 && fees_.increment == 0, + "ripple::Ledger::defaultFees : zero fees"); if (fees_.base == 0) fees_.base = config.FEES.reference_fee; if (fees_.reserve == 0) @@ -871,7 +877,7 @@ Ledger::assertSensible(beast::Journal ledgerJ) const JLOG(ledgerJ.fatal()) << "ledger is not sensible" << j; - assert(false); + UNREACHABLE("ripple::Ledger::assertSensible : ledger is not sensible"); return false; } @@ -905,7 +911,9 @@ Ledger::updateSkipList() created = false; } - assert(hashes.size() <= 256); + ASSERT( + hashes.size() <= 256, + "ripple::Ledger::updateSkipList : first maximum hashes size"); hashes.push_back(info_.parentHash); sle->setFieldV256(sfHashes, STVector256(hashes)); sle->setFieldU32(sfLastLedgerSequence, prevIndex); @@ -930,7 +938,9 @@ Ledger::updateSkipList() hashes = static_cast(sle->getFieldV256(sfHashes)); created = false; } - assert(hashes.size() <= 256); + ASSERT( + hashes.size() <= 256, + "ripple::Ledger::updateSkipList : second maximum hashes size"); if (hashes.size() == 256) hashes.erase(hashes.begin()); hashes.push_back(info_.parentHash); @@ -1010,7 +1020,8 @@ pendSaveValidated( } } - assert(ledger->isImmutable()); + ASSERT( + ledger->isImmutable(), "ripple::pendSaveValidated : immutable ledger"); if (!app.pendingSaves().shouldWork(ledger->info().seq, isSynchronous)) { @@ -1087,9 +1098,10 @@ finishLoadByIndexOrHash( if (!ledger) return; - assert( + ASSERT( ledger->info().seq < XRP_LEDGER_EARLIEST_FEES || - ledger->read(keylet::fees())); + ledger->read(keylet::fees()), + "ripple::finishLoadByIndexOrHash : valid ledger fees"); ledger->setImmutable(); JLOG(j.trace()) << "Loaded ledger: " << to_string(ledger->info().hash); @@ -1128,7 +1140,9 @@ loadByHash(uint256 const& ledgerHash, Application& app, bool acquire) { std::shared_ptr ledger = loadLedgerHelper(*info, app, acquire); finishLoadByIndexOrHash(ledger, app.config(), app.journal("Ledger")); - assert(!ledger || ledger->info().hash == ledgerHash); + ASSERT( + !ledger || ledger->info().hash == ledgerHash, + "ripple::loadByHash : ledger hash match if loaded"); return ledger; } return {}; diff --git a/src/xrpld/app/ledger/LedgerHistory.cpp b/src/xrpld/app/ledger/LedgerHistory.cpp index b63cd84772a..b12a0da0fa3 100644 --- a/src/xrpld/app/ledger/LedgerHistory.cpp +++ b/src/xrpld/app/ledger/LedgerHistory.cpp @@ -58,7 +58,9 @@ LedgerHistory::insert( if (!ledger->isImmutable()) LogicError("mutable Ledger in insert"); - assert(ledger->stateMap().getHash().isNonZero()); + ASSERT( + ledger->stateMap().getHash().isNonZero(), + "ripple::LedgerHistory::insert : nonzero hash"); std::unique_lock sl(m_ledgers_by_hash.peekMutex()); @@ -99,13 +101,17 @@ LedgerHistory::getLedgerBySeq(LedgerIndex index) if (!ret) return ret; - assert(ret->info().seq == index); + ASSERT( + ret->info().seq == index, + "ripple::LedgerHistory::getLedgerBySeq : result sequence match"); { // Add this ledger to the local tracking by index std::unique_lock sl(m_ledgers_by_hash.peekMutex()); - assert(ret->isImmutable()); + ASSERT( + ret->isImmutable(), + "ripple::LedgerHistory::getLedgerBySeq : immutable result ledger"); m_ledgers_by_hash.canonicalize_replace_client(ret->info().hash, ret); mLedgersByIndex[ret->info().seq] = ret->info().hash; return (ret->info().seq == index) ? ret : nullptr; @@ -119,8 +125,14 @@ LedgerHistory::getLedgerByHash(LedgerHash const& hash) if (ret) { - assert(ret->isImmutable()); - assert(ret->info().hash == hash); + ASSERT( + ret->isImmutable(), + "ripple::LedgerHistory::getLedgerByHash : immutable fetched " + "ledger"); + ASSERT( + ret->info().hash == hash, + "ripple::LedgerHistory::getLedgerByHash : fetched ledger hash " + "match"); return ret; } @@ -129,10 +141,16 @@ LedgerHistory::getLedgerByHash(LedgerHash const& hash) if (!ret) return ret; - assert(ret->isImmutable()); - assert(ret->info().hash == hash); + ASSERT( + ret->isImmutable(), + "ripple::LedgerHistory::getLedgerByHash : immutable loaded ledger"); + ASSERT( + ret->info().hash == hash, + "ripple::LedgerHistory::getLedgerByHash : loaded ledger hash match"); m_ledgers_by_hash.canonicalize_replace_client(ret->info().hash, ret); - assert(ret->info().hash == hash); + ASSERT( + ret->info().hash == hash, + "ripple::LedgerHistory::getLedgerByHash : result hash match"); return ret; } @@ -176,7 +194,9 @@ log_metadata_difference( auto validMetaData = getMeta(validLedger, tx); auto builtMetaData = getMeta(builtLedger, tx); - assert(validMetaData || builtMetaData); + ASSERT( + validMetaData || builtMetaData, + "ripple::log_metadata_difference : some metadata present"); if (validMetaData && builtMetaData) { @@ -320,7 +340,9 @@ LedgerHistory::handleMismatch( std::optional const& validatedConsensusHash, Json::Value const& consensus) { - assert(built != valid); + ASSERT( + built != valid, + "ripple::LedgerHistory::handleMismatch : unequal hashes"); ++mismatch_counter_; auto builtLedger = getLedgerByHash(built); @@ -335,7 +357,9 @@ LedgerHistory::handleMismatch( return; } - assert(builtLedger->info().seq == validLedger->info().seq); + ASSERT( + builtLedger->info().seq == validLedger->info().seq, + "ripple::LedgerHistory::handleMismatch : sequence match"); if (auto stream = j_.debug()) { @@ -428,7 +452,7 @@ LedgerHistory::builtLedger( { LedgerIndex index = ledger->info().seq; LedgerHash hash = ledger->info().hash; - assert(!hash.isZero()); + ASSERT(!hash.isZero(), "ripple::LedgerHistory::builtLedger : nonzero hash"); std::unique_lock sl(m_consensus_validated.peekMutex()); @@ -468,7 +492,9 @@ LedgerHistory::validatedLedger( { LedgerIndex index = ledger->info().seq; LedgerHash hash = ledger->info().hash; - assert(!hash.isZero()); + ASSERT( + !hash.isZero(), + "ripple::LedgerHistory::validatedLedger : nonzero hash"); std::unique_lock sl(m_consensus_validated.peekMutex()); diff --git a/src/xrpld/app/ledger/OpenLedger.h b/src/xrpld/app/ledger/OpenLedger.h index b218b1d6e11..2ec355fd82f 100644 --- a/src/xrpld/app/ledger/OpenLedger.h +++ b/src/xrpld/app/ledger/OpenLedger.h @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include namespace ripple { @@ -263,7 +263,8 @@ OpenLedger::apply( // If there are any transactions left, we must have // tried them in at least one final pass - assert(retries.empty() || !retry); + ASSERT( + retries.empty() || !retry, "ripple::OpenLedger::apply : valid retries"); } //------------------------------------------------------------------------------ diff --git a/src/xrpld/app/ledger/OrderBookDB.cpp b/src/xrpld/app/ledger/OrderBookDB.cpp index d0eddadbacb..926728cbf4f 100644 --- a/src/xrpld/app/ledger/OrderBookDB.cpp +++ b/src/xrpld/app/ledger/OrderBookDB.cpp @@ -225,7 +225,9 @@ OrderBookDB::makeBookListeners(Book const& book) ret = std::make_shared(); mListeners[book] = ret; - assert(getBookListeners(book) == ret); + ASSERT( + getBookListeners(book) == ret, + "ripple::OrderBookDB::makeBookListeners : result roundtrip lookup"); } return ret; diff --git a/src/xrpld/app/ledger/TransactionStateSF.cpp b/src/xrpld/app/ledger/TransactionStateSF.cpp index fac28cd2aa8..fef622945c1 100644 --- a/src/xrpld/app/ledger/TransactionStateSF.cpp +++ b/src/xrpld/app/ledger/TransactionStateSF.cpp @@ -30,7 +30,9 @@ TransactionStateSF::gotNode( SHAMapNodeType type) const { - assert(type != SHAMapNodeType::tnTRANSACTION_NM); + ASSERT( + type != SHAMapNodeType::tnTRANSACTION_NM, + "ripple::TransactionStateSF::gotNode : valid input"); db_.store( hotTRANSACTION_NODE, std::move(nodeData), diff --git a/src/xrpld/app/ledger/detail/BuildLedger.cpp b/src/xrpld/app/ledger/detail/BuildLedger.cpp index 8c4a7a3f41d..812f9dbbc05 100644 --- a/src/xrpld/app/ledger/detail/BuildLedger.cpp +++ b/src/xrpld/app/ledger/detail/BuildLedger.cpp @@ -57,7 +57,7 @@ buildLedgerImpl( { OpenView accum(&*built); - assert(!accum.open()); + ASSERT(!accum.open(), "ripple::buildLedgerImpl : valid ledger state"); applyTxs(accum, built); accum.apply(*built); } @@ -75,9 +75,10 @@ buildLedgerImpl( built->unshare(); // Accept ledger - assert( + ASSERT( built->info().seq < XRP_LEDGER_EARLIEST_FEES || - built->read(keylet::fees())); + built->read(keylet::fees()), + "ripple::buildLedgerImpl : valid ledger fees"); built->setAccepted(closeTime, closeResolution, closeTimeCorrect); return built; @@ -169,7 +170,9 @@ applyTransactions( // If there are any transactions left, we must have // tried them in at least one final pass - assert(txns.empty() || !certainRetry); + ASSERT( + txns.empty() || !certainRetry, + "ripple::applyTransactions : retry transactions"); return count; } diff --git a/src/xrpld/app/ledger/detail/InboundLedger.cpp b/src/xrpld/app/ledger/detail/InboundLedger.cpp index 16b15c2fce7..add0726719a 100644 --- a/src/xrpld/app/ledger/detail/InboundLedger.cpp +++ b/src/xrpld/app/ledger/detail/InboundLedger.cpp @@ -120,9 +120,10 @@ InboundLedger::init(ScopedLockType& collectionLock) JLOG(journal_.debug()) << "Acquiring ledger we already have in " << " local store. " << hash_; - assert( + ASSERT( mLedger->info().seq < XRP_LEDGER_EARLIEST_FEES || - mLedger->read(keylet::fees())); + mLedger->read(keylet::fees()), + "ripple::InboundLedger::init : valid ledger fees"); mLedger->setImmutable(); if (mReason == Reason::HISTORY) @@ -351,9 +352,10 @@ InboundLedger::tryDB(NodeStore::Database& srcDB) { JLOG(journal_.debug()) << "Had everything locally"; complete_ = true; - assert( + ASSERT( mLedger->info().seq < XRP_LEDGER_EARLIEST_FEES || - mLedger->read(keylet::fees())); + mLedger->read(keylet::fees()), + "ripple::InboundLedger::tryDB : valid ledger fees"); mLedger->setImmutable(); } } @@ -447,13 +449,16 @@ InboundLedger::done() std::to_string(timeouts_) + " ")) << mStats.get(); - assert(complete_ || failed_); + ASSERT( + complete_ || failed_, + "ripple::InboundLedger::done : complete or failed"); if (complete_ && !failed_ && mLedger) { - assert( + ASSERT( mLedger->info().seq < XRP_LEDGER_EARLIEST_FEES || - mLedger->read(keylet::fees())); + mLedger->read(keylet::fees()), + "ripple::InboundLedger::done : valid ledger fees"); mLedger->setImmutable(); switch (mReason) { @@ -613,7 +618,10 @@ InboundLedger::trigger(std::shared_ptr const& peer, TriggerReason reason) // if we wind up abandoning this fetch. if (mHaveHeader && !mHaveState && !failed_) { - assert(mLedger); + ASSERT( + mLedger != nullptr, + "ripple::InboundLedger::trigger : non-null ledger to read state " + "from"); if (!mLedger->stateMap().isValid()) { @@ -685,7 +693,10 @@ InboundLedger::trigger(std::shared_ptr const& peer, TriggerReason reason) if (mHaveHeader && !mHaveTransactions && !failed_) { - assert(mLedger); + ASSERT( + mLedger != nullptr, + "ripple::InboundLedger::trigger : non-null ledger to read " + "transactions from"); if (!mLedger->txMap().isValid()) { @@ -950,7 +961,7 @@ InboundLedger::takeAsRootNode(Slice const& data, SHAMapAddNode& san) if (!mHaveHeader) { - assert(false); + UNREACHABLE("ripple::InboundLedger::takeAsRootNode : no ledger header"); return false; } @@ -975,7 +986,7 @@ InboundLedger::takeTxRootNode(Slice const& data, SHAMapAddNode& san) if (!mHaveHeader) { - assert(false); + UNREACHABLE("ripple::InboundLedger::takeTxRootNode : no ledger header"); return false; } diff --git a/src/xrpld/app/ledger/detail/InboundLedgers.cpp b/src/xrpld/app/ledger/detail/InboundLedgers.cpp index f6d86a4d737..3b492de5531 100644 --- a/src/xrpld/app/ledger/detail/InboundLedgers.cpp +++ b/src/xrpld/app/ledger/detail/InboundLedgers.cpp @@ -73,7 +73,9 @@ class InboundLedgersImp : public InboundLedgers InboundLedger::Reason reason) override { auto doAcquire = [&, seq, reason]() -> std::shared_ptr { - assert(hash.isNonZero()); + ASSERT( + hash.isNonZero(), + "ripple::InboundLedgersImp::acquire::doAcquire : nonzero hash"); // probably not the right rule if (app_.getOPs().isNeedNetworkLedger() && @@ -162,7 +164,9 @@ class InboundLedgersImp : public InboundLedgers std::shared_ptr find(uint256 const& hash) override { - assert(hash.isNonZero()); + ASSERT( + hash.isNonZero(), + "ripple::InboundLedgersImp::find : nonzero input"); std::shared_ptr ret; @@ -324,7 +328,9 @@ class InboundLedgersImp : public InboundLedgers acqs.reserve(mLedgers.size()); for (auto const& it : mLedgers) { - assert(it.second); + ASSERT( + it.second != nullptr, + "ripple::InboundLedgersImp::getInfo : non-null ledger"); acqs.push_back(it); } for (auto const& it : mRecentFailures) @@ -359,7 +365,10 @@ class InboundLedgersImp : public InboundLedgers acquires.reserve(mLedgers.size()); for (auto const& it : mLedgers) { - assert(it.second); + ASSERT( + it.second != nullptr, + "ripple::InboundLedgersImp::gotFetchPack : non-null " + "ledger"); acquires.push_back(it.second); } } diff --git a/src/xrpld/app/ledger/detail/LedgerCleaner.cpp b/src/xrpld/app/ledger/detail/LedgerCleaner.cpp index 3021c691c53..7c9d0f9fd53 100644 --- a/src/xrpld/app/ledger/detail/LedgerCleaner.cpp +++ b/src/xrpld/app/ledger/detail/LedgerCleaner.cpp @@ -231,7 +231,9 @@ class LedgerCleanerImp : public LedgerCleaner }); if (shouldExit_) break; - assert(state_ == State::cleaning); + ASSERT( + state_ == State::cleaning, + "ripple::LedgerCleanerImp::run : is cleaning"); } doLedgerCleaner(); } @@ -353,7 +355,9 @@ class LedgerCleanerImp : public LedgerCleaner LedgerHash refHash = getLedgerHash(referenceLedger, refIndex); bool const nonzero(refHash.isNonZero()); - assert(nonzero); + ASSERT( + nonzero, + "ripple::LedgerCleanerImp::getHash : nonzero hash"); if (nonzero) { // We found the hash and sequence of a better reference diff --git a/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.cpp b/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.cpp index e079fb3ee27..6c19f6da4ea 100644 --- a/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.cpp +++ b/src/xrpld/app/ledger/detail/LedgerDeltaAcquire.cpp @@ -199,8 +199,12 @@ LedgerDeltaAcquire::tryBuild(std::shared_ptr const& parent) if (failed_ || !complete_ || !replayTemp_) return {}; - assert(parent->seq() + 1 == replayTemp_->seq()); - assert(parent->info().hash == replayTemp_->info().parentHash); + ASSERT( + parent->seq() + 1 == replayTemp_->seq(), + "ripple::LedgerDeltaAcquire::tryBuild : parent sequence match"); + ASSERT( + parent->info().hash == replayTemp_->info().parentHash, + "ripple::LedgerDeltaAcquire::tryBuild : parent hash match"); // build ledger LedgerReplay replayData(parent, replayTemp_, std::move(orderedTxns_)); fullLedger_ = buildLedger(replayData, tapNONE, app_, journal_); @@ -262,7 +266,7 @@ LedgerDeltaAcquire::onLedgerBuilt( void LedgerDeltaAcquire::notify(ScopedLockType& sl) { - assert(isDone()); + ASSERT(isDone(), "ripple::LedgerDeltaAcquire::notify : is done"); std::vector toCall; std::swap(toCall, dataReadyCallbacks_); auto const good = !failed_; diff --git a/src/xrpld/app/ledger/detail/LedgerMaster.cpp b/src/xrpld/app/ledger/detail/LedgerMaster.cpp index 53edef17d33..f5d55f6af23 100644 --- a/src/xrpld/app/ledger/detail/LedgerMaster.cpp +++ b/src/xrpld/app/ledger/detail/LedgerMaster.cpp @@ -47,13 +47,13 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include #include @@ -276,9 +276,11 @@ LedgerMaster::setValidLedger(std::shared_ptr const& l) mValidLedger.set(l); mValidLedgerSign = signTime.time_since_epoch().count(); - assert( + ASSERT( mValidLedgerSeq || !app_.getMaxDisallowedLedger() || - l->info().seq + max_ledger_difference_ > app_.getMaxDisallowedLedger()); + l->info().seq + max_ledger_difference_ > + app_.getMaxDisallowedLedger(), + "ripple::LedgerMaster::setValidLedger : valid ledger sequence"); (void)max_ledger_difference_; mValidLedgerSeq = l->info().seq; @@ -343,7 +345,9 @@ LedgerMaster::addHeldTransaction( bool LedgerMaster::canBeCurrent(std::shared_ptr const& ledger) { - assert(ledger); + ASSERT( + ledger != nullptr, + "ripple::LedgerMaster::canBeCurrent : non-null input"); // Never jump to a candidate ledger that precedes our // last validated ledger @@ -411,7 +415,9 @@ LedgerMaster::canBeCurrent(std::shared_ptr const& ledger) void LedgerMaster::switchLCL(std::shared_ptr const& lastClosed) { - assert(lastClosed); + ASSERT( + lastClosed != nullptr, + "ripple::LedgerMaster::switchLCL : non-null input"); if (!lastClosed->isImmutable()) LogicError("mutable ledger in switchLCL"); @@ -528,7 +534,9 @@ LedgerMaster::isValidated(ReadView const& ledger) // This ledger's hash is not the hash of the validated ledger if (hash) { - assert(hash->isNonZero()); + ASSERT( + hash->isNonZero(), + "ripple::LedgerMaster::isValidated : nonzero hash"); uint256 valHash = app_.getRelationalDatabase().getHashByIndex(seq); if (valHash == ledger.info().hash) @@ -818,7 +826,9 @@ LedgerMaster::setFullLedger( // A new ledger has been accepted as part of the trusted chain JLOG(m_journal.debug()) << "Ledger " << ledger->info().seq << " accepted :" << ledger->info().hash; - assert(ledger->stateMap().getHash().isNonZero()); + ASSERT( + ledger->stateMap().getHash().isNonZero(), + "ripple::LedgerMaster::setFullLedger : nonzero ledger state hash"); ledger->setValidated(); ledger->setFull(); @@ -1282,7 +1292,9 @@ LedgerMaster::findNewLedgersToPublish( { JLOG(m_journal.fatal()) << "Ledger: " << valSeq << " does not have hash for " << seq; - assert(false); + UNREACHABLE( + "ripple::LedgerMaster::findNewLedgersToPublish : ledger " + "not found"); } else { @@ -1369,7 +1381,9 @@ LedgerMaster::tryAdvance() app_.getJobQueue().addJob(jtADVANCE, "advanceLedger", [this]() { std::unique_lock sl(m_mutex); - assert(!mValidLedger.empty() && mAdvanceThread); + ASSERT( + !mValidLedger.empty() && mAdvanceThread, + "ripple::LedgerMaster::tryAdvance : has valid ledger"); JLOG(m_journal.trace()) << "advanceThread<"; @@ -1670,7 +1684,9 @@ LedgerMaster::walkHashBySeq( // be located easily and should contain the hash. LedgerIndex refIndex = getCandidateLedger(index); auto const refHash = hashOfSeq(*referenceLedger, refIndex, m_journal); - assert(refHash); + ASSERT( + refHash.has_value(), + "ripple::LedgerMaster::walkHashBySeq : found ledger"); if (refHash) { // Try the hash and sequence of a better reference ledger just found @@ -1695,7 +1711,10 @@ LedgerMaster::walkHashBySeq( *refHash, refIndex, reason)) { ledgerHash = hashOfSeq(*l, index, m_journal); - assert(ledgerHash); + ASSERT( + ledgerHash.has_value(), + "ripple::LedgerMaster::walkHashBySeq : has complete " + "ledger"); } } } @@ -1807,7 +1826,9 @@ LedgerMaster::fetchForHistory( scope_unlock sul{sl}; if (auto hash = getLedgerHashForHistory(missing, reason)) { - assert(hash->isNonZero()); + ASSERT( + hash->isNonZero(), + "ripple::LedgerMaster::fetchForHistory : found ledger"); auto ledger = getLedgerByHash(*hash); if (!ledger) { @@ -1834,7 +1855,9 @@ LedgerMaster::fetchForHistory( if (ledger) { auto seq = ledger->info().seq; - assert(seq == missing); + ASSERT( + seq == missing, + "ripple::LedgerMaster::fetchForHistory : sequence match"); JLOG(m_journal.trace()) << "fetchForHistory acquired " << seq; setFullLedger(ledger, false, false); int fillInProgress; @@ -1875,7 +1898,10 @@ LedgerMaster::fetchForHistory( std::uint32_t seq = missing - i; if (auto h = getLedgerHashForHistory(seq, reason)) { - assert(h->isNonZero()); + ASSERT( + h->isNonZero(), + "ripple::LedgerMaster::fetchForHistory : " + "prefetched ledger"); app_.getInboundLedgers().acquire(*h, seq, reason); } } @@ -2061,7 +2087,7 @@ populateFetchPack( std::uint32_t seq, bool withLeaves = true) { - assert(cnt != 0); + ASSERT(cnt != 0, "ripple::populateFetchPack : nonzero count input"); Serializer s(1024); diff --git a/src/xrpld/app/ledger/detail/LedgerReplayTask.cpp b/src/xrpld/app/ledger/detail/LedgerReplayTask.cpp index d7f29e33b3b..e03137a8b09 100644 --- a/src/xrpld/app/ledger/detail/LedgerReplayTask.cpp +++ b/src/xrpld/app/ledger/detail/LedgerReplayTask.cpp @@ -32,7 +32,10 @@ LedgerReplayTask::TaskParameter::TaskParameter( std::uint32_t totalNumLedgers) : reason_(r), finishHash_(finishLedgerHash), totalLedgers_(totalNumLedgers) { - assert(finishLedgerHash.isNonZero() && totalNumLedgers > 0); + ASSERT( + finishLedgerHash.isNonZero() && totalNumLedgers > 0, + "ripple::LedgerReplayTask::TaskParameter::TaskParameter : valid " + "inputs"); } bool @@ -48,7 +51,9 @@ LedgerReplayTask::TaskParameter::update( skipList_ = sList; skipList_.emplace_back(finishHash_); startHash_ = skipList_[skipList_.size() - totalLedgers_]; - assert(startHash_.isNonZero()); + ASSERT( + startHash_.isNonZero(), + "ripple::LedgerReplayTask::TaskParameter::update : nonzero start hash"); startSeq_ = finishSeq_ - totalLedgers_ + 1; full_ = true; return true; @@ -200,7 +205,9 @@ LedgerReplayTask::tryAdvance(ScopedLockType& sl) for (; deltaToBuild_ < deltas_.size(); ++deltaToBuild_) { auto& delta = deltas_[deltaToBuild_]; - assert(parent_->seq() + 1 == delta->ledgerSeq_); + ASSERT( + parent_->seq() + 1 == delta->ledgerSeq_, + "ripple::LedgerReplayTask::tryAdvance : consecutive sequence"); if (auto l = delta->tryBuild(parent_); l) { JLOG(journal_.debug()) @@ -289,9 +296,11 @@ LedgerReplayTask::addDelta(std::shared_ptr const& delta) JLOG(journal_.trace()) << "addDelta task " << hash_ << " deltaIndex=" << deltaToBuild_ << " totalDeltas=" << deltas_.size(); - assert( + ASSERT( deltas_.empty() || - deltas_.back()->ledgerSeq_ + 1 == delta->ledgerSeq_); + deltas_.back()->ledgerSeq_ + 1 == delta->ledgerSeq_, + "ripple::LedgerReplayTask::addDelta : no deltas or consecutive " + "sequence", ); deltas_.push_back(delta); } } diff --git a/src/xrpld/app/ledger/detail/LedgerReplayer.cpp b/src/xrpld/app/ledger/detail/LedgerReplayer.cpp index 4aa0e4beb79..7557d9ed344 100644 --- a/src/xrpld/app/ledger/detail/LedgerReplayer.cpp +++ b/src/xrpld/app/ledger/detail/LedgerReplayer.cpp @@ -47,9 +47,10 @@ LedgerReplayer::replay( uint256 const& finishLedgerHash, std::uint32_t totalNumLedgers) { - assert( + ASSERT( finishLedgerHash.isNonZero() && totalNumLedgers > 0 && - totalNumLedgers <= LedgerReplayParameters::MAX_TASK_SIZE); + totalNumLedgers <= LedgerReplayParameters::MAX_TASK_SIZE, + "ripple::LedgerReplayer::replay : valid inputs"); LedgerReplayTask::TaskParameter parameter( r, finishLedgerHash, totalNumLedgers); diff --git a/src/xrpld/app/ledger/detail/SkipListAcquire.cpp b/src/xrpld/app/ledger/detail/SkipListAcquire.cpp index 1d1de62b61b..3b3952a5557 100644 --- a/src/xrpld/app/ledger/detail/SkipListAcquire.cpp +++ b/src/xrpld/app/ledger/detail/SkipListAcquire.cpp @@ -139,7 +139,9 @@ SkipListAcquire::processData( std::uint32_t ledgerSeq, boost::intrusive_ptr const& item) { - assert(ledgerSeq != 0 && item); + ASSERT( + ledgerSeq != 0 && item, + "ripple::SkipListAcquire::processData : valid inputs"); ScopedLockType sl(mtx_); if (isDone()) return; @@ -224,7 +226,7 @@ SkipListAcquire::onSkipListAcquired( void SkipListAcquire::notify(ScopedLockType& sl) { - assert(isDone()); + ASSERT(isDone(), "ripple::SkipListAcquire::notify : is done"); std::vector toCall; std::swap(toCall, dataReadyCallbacks_); auto const good = !failed_; diff --git a/src/xrpld/app/ledger/detail/TimeoutCounter.cpp b/src/xrpld/app/ledger/detail/TimeoutCounter.cpp index f70e54f8cd4..1d8efca37f9 100644 --- a/src/xrpld/app/ledger/detail/TimeoutCounter.cpp +++ b/src/xrpld/app/ledger/detail/TimeoutCounter.cpp @@ -43,7 +43,9 @@ TimeoutCounter::TimeoutCounter( , queueJobParameter_(std::move(jobParameter)) , timer_(app_.getIOService()) { - assert((timerInterval_ > 10ms) && (timerInterval_ < 30s)); + ASSERT( + (timerInterval_ > 10ms) && (timerInterval_ < 30s), + "ripple::TimeoutCounter::TimeoutCounter : interval input inside range"); } void diff --git a/src/xrpld/app/main/Application.cpp b/src/xrpld/app/main/Application.cpp index a9d66679010..c10862d8217 100644 --- a/src/xrpld/app/main/Application.cpp +++ b/src/xrpld/app/main/Application.cpp @@ -586,7 +586,10 @@ class ApplicationImp : public Application, public BasicApp virtual ServerHandler& getServerHandler() override { - assert(serverHandler_); + ASSERT( + serverHandler_ != nullptr, + "ripple::ApplicationImp::getServerHandler : non-null server " + "handle"); return *serverHandler_; } @@ -792,28 +795,37 @@ class ApplicationImp : public Application, public BasicApp Overlay& overlay() override { - assert(overlay_); + ASSERT( + overlay_ != nullptr, + "ripple::ApplicationImp::overlay : non-null overlay"); return *overlay_; } TxQ& getTxQ() override { - assert(txQ_.get() != nullptr); + ASSERT( + txQ_.get() != nullptr, + "ripple::ApplicationImp::getTxQ : non-null transaction queue"); return *txQ_; } RelationalDatabase& getRelationalDatabase() override { - assert(mRelationalDatabase.get() != nullptr); + ASSERT( + mRelationalDatabase.get() != nullptr, + "ripple::ApplicationImp::getRelationalDatabase : non-null " + "relational database"); return *mRelationalDatabase; } DatabaseCon& getWalletDB() override { - assert(mWalletDB.get() != nullptr); + ASSERT( + mWalletDB.get() != nullptr, + "ripple::ApplicationImp::getWalletDB : non-null wallet database"); return *mWalletDB; } @@ -828,7 +840,10 @@ class ApplicationImp : public Application, public BasicApp bool initRelationalDatabase() { - assert(mWalletDB.get() == nullptr); + ASSERT( + mWalletDB.get() == nullptr, + "ripple::ApplicationImp::initRelationalDatabase : null wallet " + "database"); try { @@ -1230,7 +1245,9 @@ ApplicationImp::setup(boost::program_options::variables_map const& cmdline) for (auto const& [a, vote] : amendments) { auto const f = ripple::getRegisteredFeature(a); - assert(f); + ASSERT( + f.has_value(), + "ripple::ApplicationImp::setup : registered feature"); if (f) supported.emplace_back(a, *f, vote); } @@ -1693,9 +1710,10 @@ ApplicationImp::startGenesisLedger() auto const next = std::make_shared(*genesis, timeKeeper().closeTime()); next->updateSkipList(); - assert( + ASSERT( next->info().seq < XRP_LEDGER_EARLIEST_FEES || - next->read(keylet::fees())); + next->read(keylet::fees()), + "ripple::ApplicationImp::startGenesisLedger : valid ledger fees"); next->setImmutable(); openLedger_.emplace(next, cachedSLEs_, logs_->journal("OpenLedger")); m_ledgerMaster->storeLedger(next); @@ -1714,9 +1732,10 @@ ApplicationImp::getLastFullLedger() if (!ledger) return ledger; - assert( + ASSERT( ledger->info().seq < XRP_LEDGER_EARLIEST_FEES || - ledger->read(keylet::fees())); + ledger->read(keylet::fees()), + "ripple::ApplicationImp::getLastFullLedger : valid ledger fees"); ledger->setImmutable(); if (getLedgerMaster().haveLedger(seq)) @@ -1868,9 +1887,10 @@ ApplicationImp::loadLedgerFromFile(std::string const& name) loadLedger->stateMap().flushDirty(hotACCOUNT_NODE); - assert( + ASSERT( loadLedger->info().seq < XRP_LEDGER_EARLIEST_FEES || - loadLedger->read(keylet::fees())); + loadLedger->read(keylet::fees()), + "ripple::ApplicationImp::loadLedgerFromFile : valid ledger fees"); loadLedger->setAccepted( closeTime, closeTimeResolution, !closeTimeEstimated); @@ -1968,7 +1988,9 @@ ApplicationImp::loadOldLedger( if (!loadLedger) { JLOG(m_journal.fatal()) << "Replay ledger missing/damaged"; - assert(false); + UNREACHABLE( + "ripple::ApplicationImp::loadOldLedger : replay ledger " + "missing/damaged"); return false; } } @@ -1997,21 +2019,26 @@ ApplicationImp::loadOldLedger( if (loadLedger->info().accountHash.isZero()) { JLOG(m_journal.fatal()) << "Ledger is empty."; - assert(false); + UNREACHABLE( + "ripple::ApplicationImp::loadOldLedger : ledger is empty"); return false; } if (!loadLedger->walkLedger(journal("Ledger"), true)) { JLOG(m_journal.fatal()) << "Ledger is missing nodes."; - assert(false); + UNREACHABLE( + "ripple::ApplicationImp::loadOldLedger : ledger is missing " + "nodes"); return false; } if (!loadLedger->assertSensible(journal("Ledger"))) { JLOG(m_journal.fatal()) << "Ledger is not sensible."; - assert(false); + UNREACHABLE( + "ripple::ApplicationImp::loadOldLedger : ledger is not " + "sensible"); return false; } diff --git a/src/xrpld/app/main/GRPCServer.cpp b/src/xrpld/app/main/GRPCServer.cpp index 5a231dfc9e6..c4a1b2458c9 100644 --- a/src/xrpld/app/main/GRPCServer.cpp +++ b/src/xrpld/app/main/GRPCServer.cpp @@ -606,7 +606,7 @@ GRPCServer::stop() GRPCServer::~GRPCServer() { - assert(!running_); + ASSERT(!running_, "ripple::GRPCServer::~GRPCServer : is not running"); } } // namespace ripple diff --git a/src/xrpld/app/main/LoadManager.cpp b/src/xrpld/app/main/LoadManager.cpp index f5dd8719470..181007305ef 100644 --- a/src/xrpld/app/main/LoadManager.cpp +++ b/src/xrpld/app/main/LoadManager.cpp @@ -73,7 +73,9 @@ void LoadManager::start() { JLOG(journal_.debug()) << "Starting"; - assert(!thread_.joinable()); + ASSERT( + !thread_.joinable(), + "ripple::LoadManager::start : thread not joinable"); thread_ = std::thread{&LoadManager::run, this}; } diff --git a/src/xrpld/app/main/Main.cpp b/src/xrpld/app/main/Main.cpp index 169a6dad912..2b47ac9795b 100644 --- a/src/xrpld/app/main/Main.cpp +++ b/src/xrpld/app/main/Main.cpp @@ -69,6 +69,10 @@ #error Multiple supported platforms appear active at once #endif +#ifdef ENABLE_VOIDSTAR +#include "antithesis_instrumentation.h" +#endif + namespace po = boost::program_options; namespace ripple { diff --git a/src/xrpld/app/main/NodeStoreScheduler.cpp b/src/xrpld/app/main/NodeStoreScheduler.cpp index bf07e559fd3..f2dce5421f0 100644 --- a/src/xrpld/app/main/NodeStoreScheduler.cpp +++ b/src/xrpld/app/main/NodeStoreScheduler.cpp @@ -18,7 +18,7 @@ //============================================================================== #include -#include +#include namespace ripple { diff --git a/src/xrpld/app/misc/FeeVoteImpl.cpp b/src/xrpld/app/misc/FeeVoteImpl.cpp index cb4e57b0f73..7943bbe97a7 100644 --- a/src/xrpld/app/misc/FeeVoteImpl.cpp +++ b/src/xrpld/app/misc/FeeVoteImpl.cpp @@ -200,7 +200,9 @@ FeeVoteImpl::doVoting( std::shared_ptr const& initialPosition) { // LCL must be flag ledger - assert(lastClosedLedger && isFlagLedger(lastClosedLedger->seq())); + ASSERT( + lastClosedLedger && isFlagLedger(lastClosedLedger->seq()), + "ripple::FeeVoteImpl::doVoting : has a flag ledger"); detail::VotableValue baseFeeVote( lastClosedLedger->fees().base, target_.reference_fee); diff --git a/src/xrpld/app/misc/HashRouter.cpp b/src/xrpld/app/misc/HashRouter.cpp index c117d20fe2b..44133dddf9b 100644 --- a/src/xrpld/app/misc/HashRouter.cpp +++ b/src/xrpld/app/misc/HashRouter.cpp @@ -101,7 +101,7 @@ HashRouter::getFlags(uint256 const& key) bool HashRouter::setFlags(uint256 const& key, int flags) { - assert(flags != 0); + ASSERT(flags != 0, "ripple::HashRouter::setFlags : valid input"); std::lock_guard lock(mutex_); diff --git a/src/xrpld/app/misc/NegativeUNLVote.cpp b/src/xrpld/app/misc/NegativeUNLVote.cpp index 45d72bcd2b3..b8f485c3dc0 100644 --- a/src/xrpld/app/misc/NegativeUNLVote.cpp +++ b/src/xrpld/app/misc/NegativeUNLVote.cpp @@ -89,7 +89,9 @@ NegativeUNLVote::doVoting( { auto n = choose(prevLedger->info().hash, candidates.toDisableCandidates); - assert(nidToKeyMap.count(n)); + ASSERT( + nidToKeyMap.count(n) != 0, + "ripple::NegativeUNLVote::doVoting : found node to disable"); addTx(seq, nidToKeyMap.at(n), ToDisable, initialSet); } @@ -97,7 +99,9 @@ NegativeUNLVote::doVoting( { auto n = choose( prevLedger->info().hash, candidates.toReEnableCandidates); - assert(nidToKeyMap.count(n)); + ASSERT( + nidToKeyMap.count(n) != 0, + "ripple::NegativeUNLVote::doVoting : found node to enable"); addTx(seq, nidToKeyMap.at(n), ToReEnable, initialSet); } } @@ -140,7 +144,9 @@ NegativeUNLVote::choose( uint256 const& randomPadData, std::vector const& candidates) { - assert(!candidates.empty()); + ASSERT( + !candidates.empty(), + "ripple::NegativeUNLVote::choose : non-empty input"); static_assert(NodeID::bytes <= uint256::bytes); NodeID randomPad = NodeID::fromVoid(randomPadData.data()); NodeID txNodeID = candidates[0]; diff --git a/src/xrpld/app/misc/NetworkOPs.cpp b/src/xrpld/app/misc/NetworkOPs.cpp index d647df91f1e..e7432b4de0c 100644 --- a/src/xrpld/app/misc/NetworkOPs.cpp +++ b/src/xrpld/app/misc/NetworkOPs.cpp @@ -105,7 +105,10 @@ class NetworkOPsImp final : public NetworkOPs FailHard f) : transaction(t), admin(a), local(l), failType(f) { - assert(local || failType == FailHard::no); + ASSERT( + local || failType == FailHard::no, + "ripple::NetworkOPsImp::TransactionStatus::TransactionStatus : " + "valid inputs"); } }; @@ -1210,7 +1213,9 @@ NetworkOPsImp::processTransaction( *transaction->getSTransaction(), view->rules(), app_.config()); - assert(validity == Validity::Valid); + ASSERT( + validity == Validity::Valid, + "ripple::NetworkOPsImp::processTransaction : valid validity"); // Not concerned with local checks at this point. if (validity == Validity::SigBad) @@ -1316,9 +1321,13 @@ NetworkOPsImp::apply(std::unique_lock& batchLock) std::vector submit_held; std::vector transactions; mTransactions.swap(transactions); - assert(!transactions.empty()); + ASSERT( + !transactions.empty(), + "ripple::NetworkOPsImp::apply : non-empty transactions"); + ASSERT( + mDispatchState != DispatchState::running, + "ripple::NetworkOPsImp::apply : is not running"); - assert(mDispatchState != DispatchState::running); mDispatchState = DispatchState::running; batchLock.unlock(); @@ -1534,7 +1543,9 @@ NetworkOPsImp::getOwnerInfo( for (auto const& uDirEntry : sleNode->getFieldV256(sfIndexes)) { auto sleCur = lpLedger->read(keylet::child(uDirEntry)); - assert(sleCur); + ASSERT( + sleCur != nullptr, + "ripple::NetworkOPsImp::getOwnerInfo : non-null child SLE"); switch (sleCur->getType()) { @@ -1561,7 +1572,9 @@ NetworkOPsImp::getOwnerInfo( case ltACCOUNT_ROOT: case ltDIR_NODE: default: - assert(false); + UNREACHABLE( + "ripple::NetworkOPsImp::getOwnerInfo : invalid " + "type"); break; } } @@ -1571,7 +1584,9 @@ NetworkOPsImp::getOwnerInfo( if (uNodeDir) { sleNode = lpLedger->read(keylet::page(root, uNodeDir)); - assert(sleNode); + ASSERT( + sleNode != nullptr, + "ripple::NetworkOPsImp::getOwnerInfo : read next page"); } } while (uNodeDir); } @@ -1802,7 +1817,9 @@ NetworkOPsImp::switchLastClosedLedger( bool NetworkOPsImp::beginConsensus(uint256 const& networkClosed) { - assert(networkClosed.isNonZero()); + ASSERT( + networkClosed.isNonZero(), + "ripple::NetworkOPsImp::beginConsensus : nonzero input"); auto closingInfo = m_ledgerMaster.getCurrentLedger()->info(); @@ -1823,10 +1840,14 @@ NetworkOPsImp::beginConsensus(uint256 const& networkClosed) return false; } - assert(prevLedger->info().hash == closingInfo.parentHash); - assert( - closingInfo.parentHash == - m_ledgerMaster.getClosedLedger()->info().hash); + ASSERT( + prevLedger->info().hash == closingInfo.parentHash, + "ripple::NetworkOPsImp::beginConsensus : prevLedger hash matches " + "parent"); + ASSERT( + closingInfo.parentHash == m_ledgerMaster.getClosedLedger()->info().hash, + "ripple::NetworkOPsImp::beginConsensus : closedLedger parent matches " + "hash"); if (prevLedger->rules().enabled(featureNegativeUNL)) app_.validators().setNegativeUNL(prevLedger->negativeUNL()); @@ -2799,7 +2820,9 @@ NetworkOPsImp::pubLedger(std::shared_ptr const& lpAccepted) lpAccepted->info().hash, alpAccepted); } - assert(alpAccepted->getLedger().get() == lpAccepted.get()); + ASSERT( + alpAccepted->getLedger().get() == lpAccepted.get(), + "ripple::NetworkOPsImp::pubLedger : accepted input"); { JLOG(m_journal.debug()) @@ -3202,9 +3225,11 @@ NetworkOPsImp::pubAccountTransaction( if (last) jvObj.set(jss::account_history_boundary, true); - assert( + ASSERT( jvObj.isMember(jss::account_history_tx_stream) == - MultiApiJson::none); + MultiApiJson::none, + "ripple::NetworkOPsImp::pubAccountTransaction : " + "account_history_tx_stream not set"); for (auto& info : accountHistoryNotify) { auto& index = info.index_; @@ -3277,9 +3302,11 @@ NetworkOPsImp::pubProposedAccountTransaction( isrListener->getApiVersion(), // [&](Json::Value const& jv) { isrListener->send(jv, true); }); - assert( + ASSERT( jvObj.isMember(jss::account_history_tx_stream) == - MultiApiJson::none); + MultiApiJson::none, + "ripple::NetworkOPs::pubProposedAccountTransaction : " + "account_history_tx_stream not set"); for (auto& info : accountHistoryNotify) { auto& index = info.index_; @@ -3500,7 +3527,9 @@ NetworkOPsImp::addAccountHistoryJob(SubAccountHistoryInfoWeak subInfo) return db->newestAccountTxPage(options); } default: { - assert(false); + UNREACHABLE( + "ripple::NetworkOPsImp::addAccountHistoryJob::" + "getMoreTxns : invalid database type"); return {}; } } @@ -3696,7 +3725,9 @@ NetworkOPsImp::subAccountHistoryStart( } else { - assert(false); + UNREACHABLE( + "ripple::NetworkOPsImp::subAccountHistoryStart : failed to " + "access genesis account"); return; } } @@ -3804,7 +3835,7 @@ NetworkOPsImp::subBook(InfoSub::ref isrListener, Book const& book) if (auto listeners = app_.getOrderBookDB().makeBookListeners(book)) listeners->addSubscriber(isrListener); else - assert(false); + UNREACHABLE("ripple::NetworkOPsImp::subBook : null book listeners"); return true; } @@ -3823,7 +3854,7 @@ NetworkOPsImp::acceptLedger( { // This code-path is exclusively used when the server is in standalone // mode via `ledger_accept` - assert(m_standalone); + ASSERT(m_standalone, "ripple::NetworkOPsImp::acceptLedger : is standalone"); if (!m_standalone) Throw( diff --git a/src/xrpld/app/misc/SHAMapStoreImp.cpp b/src/xrpld/app/misc/SHAMapStoreImp.cpp index 1ce862b095f..2913ebb857f 100644 --- a/src/xrpld/app/misc/SHAMapStoreImp.cpp +++ b/src/xrpld/app/misc/SHAMapStoreImp.cpp @@ -513,7 +513,9 @@ SHAMapStoreImp::clearSql( std::function()> const& getMinSeq, std::function const& deleteBeforeSeq) { - assert(deleteInterval_); + ASSERT( + deleteInterval_ != 0, + "ripple::SHAMapStoreImp::clearSql : nonzero delete interval"); LedgerIndex min = std::numeric_limits::max(); { diff --git a/src/xrpld/app/misc/detail/AMMHelpers.cpp b/src/xrpld/app/misc/detail/AMMHelpers.cpp index f10b4c15eb0..4e23a607502 100644 --- a/src/xrpld/app/misc/detail/AMMHelpers.cpp +++ b/src/xrpld/app/misc/detail/AMMHelpers.cpp @@ -209,7 +209,9 @@ adjustAmountsByLPTokens( return std::make_tuple(amountActual, std::nullopt, lpTokensActual); } - assert(lpTokensActual == lpTokens); + ASSERT( + lpTokensActual == lpTokens, + "ripple::adjustAmountsByLPTokens : LP tokens match actual"); return {amount, amount2, lpTokensActual}; } diff --git a/src/xrpld/app/misc/detail/AMMUtils.cpp b/src/xrpld/app/misc/detail/AMMUtils.cpp index efc80cf17b6..c91f0c56642 100644 --- a/src/xrpld/app/misc/detail/AMMUtils.cpp +++ b/src/xrpld/app/misc/detail/AMMUtils.cpp @@ -145,9 +145,10 @@ std::uint16_t getTradingFee(ReadView const& view, SLE const& ammSle, AccountID const& account) { using namespace std::chrono; - assert( + ASSERT( !view.rules().enabled(fixInnerObjTemplate) || - ammSle.isFieldPresent(sfAuctionSlot)); + ammSle.isFieldPresent(sfAuctionSlot), + "ripple::getTradingFee : auction present"); if (ammSle.isFieldPresent(sfAuctionSlot)) { auto const& auctionSlot = diff --git a/src/xrpld/app/misc/detail/AmendmentTable.cpp b/src/xrpld/app/misc/detail/AmendmentTable.cpp index 62b80890821..a35eb72efeb 100644 --- a/src/xrpld/app/misc/detail/AmendmentTable.cpp +++ b/src/xrpld/app/misc/detail/AmendmentTable.cpp @@ -656,7 +656,9 @@ AmendmentTableImpl::persistVote( std::string const& name, AmendmentVote vote) const { - assert(vote != AmendmentVote::obsolete); + ASSERT( + vote != AmendmentVote::obsolete, + "ripple::AmendmentTableImpl::persistVote : valid vote input"); auto db = db_.checkoutDb(); voteAmendment(*db, amendment, name, vote); } diff --git a/src/xrpld/app/misc/detail/Manifest.cpp b/src/xrpld/app/misc/detail/Manifest.cpp index a17858ceb39..bf3b58cc9d9 100644 --- a/src/xrpld/app/misc/detail/Manifest.cpp +++ b/src/xrpld/app/misc/detail/Manifest.cpp @@ -390,7 +390,9 @@ ManifestCache::applyManifest(Manifest m) auto prewriteCheck = [this, &m](auto const& iter, bool checkSignature, auto const& lock) -> std::optional { - assert(lock.owns_lock()); + ASSERT( + lock.owns_lock(), + "ripple::ManifestCache::applyManifest::prewriteCheck : locked"); (void)lock; // not used. parameter is present to ensure the mutex is // locked when the lambda is called. if (iter != map_.end() && m.sequence <= iter->second.sequence) diff --git a/src/xrpld/app/misc/detail/Transaction.cpp b/src/xrpld/app/misc/detail/Transaction.cpp index c8f9df232e0..27cb785eb78 100644 --- a/src/xrpld/app/misc/detail/Transaction.cpp +++ b/src/xrpld/app/misc/detail/Transaction.cpp @@ -82,7 +82,10 @@ Transaction::sqlTransactionStatus(boost::optional const& status) return INCLUDED; } - assert(c == txnSqlUnknown); + ASSERT( + c == txnSqlUnknown, + "ripple::Transaction::sqlTransactionStatus : unknown transaction " + "status"); return INVALID; } diff --git a/src/xrpld/app/misc/detail/TxQ.cpp b/src/xrpld/app/misc/detail/TxQ.cpp index a4e62b382a7..9f886fd2977 100644 --- a/src/xrpld/app/misc/detail/TxQ.cpp +++ b/src/xrpld/app/misc/detail/TxQ.cpp @@ -52,7 +52,7 @@ getFeeLevelPaid(ReadView const& view, STTx const& tx) return std::pair{baseFee + mod, feePaid + mod}; }(); - assert(baseFee.signum() > 0); + ASSERT(baseFee.signum() > 0, "ripple::getFeeLevelPaid : positive fee"); if (effectiveFeePaid.signum() <= 0 || baseFee.signum() <= 0) { return FeeLevel64(0); @@ -95,7 +95,9 @@ TxQ::FeeMetrics::update( feeLevels.push_back(getFeeLevelPaid(view, *tx.first)); }); std::sort(feeLevels.begin(), feeLevels.end()); - assert(size == feeLevels.size()); + ASSERT( + size == feeLevels.size(), + "ripple::TxQ::FeeMetrics::update : fee levels size"); JLOG((timeLeap ? j_.warn() : j_.debug())) << "Ledger " << view.info().seq << " has " << size << " transactions. " @@ -247,7 +249,10 @@ TxQ::FeeMetrics::escalatedSeriesFeeLevel( auto const target = snapshot.txnsExpected; auto const multiplier = snapshot.escalationMultiplier; - assert(current > target); + ASSERT( + current > target, + "ripple::TxQ::FeeMetrics::escalatedSeriesFeeLevel : current over " + "target"); /* Calculate (apologies for the terrible notation) sum(n = current -> last) : multiplier * n * n / (target * target) @@ -292,7 +297,9 @@ std::pair TxQ::MaybeTx::apply(Application& app, OpenView& view, beast::Journal j) { // If the rules or flags change, preflight again - assert(pfresult); + ASSERT( + pfresult.has_value(), + "ripple::TxQ::MaybeTx::apply : preflight result is set"); STAmountSO stAmountSO{view.rules().enabled(fixSTAmountCanonicalize)}; NumberSO stNumberSO{view.rules().enabled(fixUniversalNumber)}; @@ -337,8 +344,10 @@ TxQ::TxQAccount::add(MaybeTx&& txn) auto const seqProx = txn.seqProxy; auto result = transactions.emplace(seqProx, std::move(txn)); - assert(result.second); - assert(&result.first->second != &txn); + ASSERT(result.second, "ripple::TxQ::TxQAccount::add : emplace succeeded"); + ASSERT( + &result.first->second != &txn, + "ripple::TxQ::TxQAccount::add : transaction moved"); return result.first->second; } @@ -446,9 +455,8 @@ TxQ::erase(TxQ::FeeMultiSet::const_iterator_type candidateIter) // Now that the candidate has been removed from the // intrusive list remove it from the TxQAccount // so the memory can be freed. - auto const found = txQAccount.remove(seqProx); - (void)found; - assert(found); + [[maybe_unused]] auto const found = txQAccount.remove(seqProx); + ASSERT(found, "ripple::TxQ::erase : account removed"); return newCandidateIter; } @@ -460,15 +468,20 @@ TxQ::eraseAndAdvance(TxQ::FeeMultiSet::const_iterator_type candidateIter) auto& txQAccount = byAccount_.at(candidateIter->account); auto const accountIter = txQAccount.transactions.find(candidateIter->seqProxy); - assert(accountIter != txQAccount.transactions.end()); + ASSERT( + accountIter != txQAccount.transactions.end(), + "ripple::TxQ::eraseAndAdvance : account found"); // Note that sequence-based transactions must be applied in sequence order // from smallest to largest. But ticket-based transactions can be // applied in any order. - assert( + ASSERT( candidateIter->seqProxy.isTicket() || - accountIter == txQAccount.transactions.begin()); - assert(byFee_.iterator_to(accountIter->second) == candidateIter); + accountIter == txQAccount.transactions.begin(), + "ripple::TxQ::eraseAndAdvance : ticket or sequence"); + ASSERT( + byFee_.iterator_to(accountIter->second) == candidateIter, + "ripple::TxQ::eraseAndAdvance : found in byFee"); auto const accountNextIter = std::next(accountIter); // Check if the next transaction for this account is earlier in the queue, @@ -515,7 +528,9 @@ TxQ::tryClearAccountQueueUpThruTx( beast::Journal j) { SeqProxy const tSeqProx{tx.getSeqProxy()}; - assert(beginTxIter != accountIter->second.transactions.end()); + ASSERT( + beginTxIter != accountIter->second.transactions.end(), + "ripple::TxQ::tryClearAccountQueueUpThruTx : non-empty accounts input"); // This check is only concerned with the range from // [aSeqProxy, tSeqProxy) @@ -998,7 +1013,7 @@ TxQ::apply( // o The current first thing in the queue has a Ticket and // * The tx has a Ticket that precedes it or // * txSeqProx == acctSeqProx. - assert(prevIter != txIter->end); + ASSERT(prevIter != txIter->end, "ripple::TxQ::apply : not end"); if (prevIter == txIter->end || txSeqProx < prevIter->first) { // The first Sequence number in the queue must be the @@ -1119,10 +1134,11 @@ TxQ::apply( // inserted in the middle from fouling up later transactions. auto const potentialTotalSpend = totalFee + std::min(balance - std::min(balance, reserve), potentialSpend); - assert( + ASSERT( potentialTotalSpend > XRPAmount{0} || - (potentialTotalSpend == XRPAmount{0} && - multiTxn->applyView.fees().base == 0)); + (potentialTotalSpend == XRPAmount{0} && + multiTxn->applyView.fees().base == 0), + "ripple::TxQ::apply : total spend check"); sleBump->setFieldAmount(sfBalance, balance - potentialTotalSpend); // The transaction's sequence/ticket will be valid when the other // transactions in the queue have been processed. If the tx has a @@ -1152,7 +1168,7 @@ TxQ::apply( return {pcresult.ter, false}; // Too low of a fee should get caught by preclaim - assert(feeLevelPaid >= baseLevel); + ASSERT(feeLevelPaid >= baseLevel, "ripple::TxQ::apply : minimum fee"); JLOG(j_.trace()) << "Transaction " << transactionID << " from account " << account << " has fee level of " << feeLevelPaid @@ -1277,7 +1293,9 @@ TxQ::apply( // The queue is full, and this transaction is more // valuable, so kick out the cheapest transaction. auto dropRIter = endAccount.transactions.rbegin(); - assert(dropRIter->second.account == lastRIter->account); + ASSERT( + dropRIter->second.account == lastRIter->account, + "ripple::TxQ::apply : cheapest transaction found"); JLOG(j_.info()) << "Removing last item of account " << lastRIter->account << " from queue with average fee of " << endEffectiveFeeLevel @@ -1303,11 +1321,10 @@ TxQ::apply( if (!accountIsInQueue) { // Create a new TxQAccount object and add the byAccount lookup. - bool created; + [[maybe_unused]] bool created = false; std::tie(accountIter, created) = byAccount_.emplace(account, TxQAccount(tx)); - (void)created; - assert(created); + ASSERT(created, "ripple::TxQ::apply : account created"); } // Modify the flags for use when coming out of the queue. // These changes _may_ cause an extra `preflight`, but as long as @@ -1520,9 +1537,9 @@ TxQ::accept(Application& app, OpenView& view) // making things worse, drop the _last_ transaction for // this account. auto dropRIter = account.transactions.rbegin(); - assert( - dropRIter->second.account == - candidateIter->account); + ASSERT( + dropRIter->second.account == candidateIter->account, + "ripple::TxQ::accept : account check"); JLOG(j_.info()) << "Queue is nearly full, and transaction " @@ -1553,7 +1570,7 @@ TxQ::accept(Application& app, OpenView& view) LedgerHash const& parentHash = view.info().parentHash; #if !NDEBUG auto const startingSize = byFee_.size(); - assert(parentHash != parentHash_); + ASSERT(parentHash != parentHash_, "ripple::TxQ::accept : new parent hash"); parentHash_ = parentHash; #endif // byFee_ doesn't "own" the candidate objects inside it, so it's @@ -1575,7 +1592,9 @@ TxQ::accept(Application& app, OpenView& view) byFee_.insert(candidate); } } - assert(byFee_.size() == startingSize); + ASSERT( + byFee_.size() == startingSize, + "ripple::TxQ::accept : byFee size match"); return ledgerChanged; } @@ -1734,10 +1753,18 @@ TxQ::removeFromByFee( // If the transaction we're holding replaces a transaction in the // queue, remove the transaction that is being replaced. auto deleteIter = byFee_.iterator_to((*replacedTxIter)->second); - assert(deleteIter != byFee_.end()); - assert(&(*replacedTxIter)->second == &*deleteIter); - assert(deleteIter->seqProxy == tx->getSeqProxy()); - assert(deleteIter->account == (*tx)[sfAccount]); + ASSERT( + deleteIter != byFee_.end(), + "ripple::TxQ::removeFromByFee : found in byFee"); + ASSERT( + &(*replacedTxIter)->second == &*deleteIter, + "ripple::TxQ::removeFromByFee : matching transaction"); + ASSERT( + deleteIter->seqProxy == tx->getSeqProxy(), + "ripple::TxQ::removeFromByFee : matching sequence"); + ASSERT( + deleteIter->account == (*tx)[sfAccount], + "ripple::TxQ::removeFromByFee : matching account"); erase(deleteIter); } diff --git a/src/xrpld/app/misc/detail/ValidatorList.cpp b/src/xrpld/app/misc/detail/ValidatorList.cpp index 9a323e0116b..052cecb80b1 100644 --- a/src/xrpld/app/misc/detail/ValidatorList.cpp +++ b/src/xrpld/app/misc/detail/ValidatorList.cpp @@ -276,7 +276,9 @@ ValidatorList::buildFileData( { Json::Value value(Json::objectValue); - assert(pubCollection.rawVersion == 2 || pubCollection.remaining.empty()); + ASSERT( + pubCollection.rawVersion == 2 || pubCollection.remaining.empty(), + "ripple::ValidatorList::buildFileData : valid publisher list input"); auto const effectiveVersion = forceVersion ? *forceVersion : pubCollection.rawVersion; @@ -376,7 +378,9 @@ ValidatorList::parseBlobs(std::uint32_t version, Json::Value const& body) ValidatorBlobInfo& info = result.emplace_back(); info.blob = body[jss::blob].asString(); info.signature = body[jss::signature].asString(); - assert(result.size() == 1); + ASSERT( + result.size() == 1, + "ripple::ValidatorList::parseBlobs : single element result"); return result; } // Treat unknown versions as if they're the latest version. This @@ -411,7 +415,10 @@ ValidatorList::parseBlobs(std::uint32_t version, Json::Value const& body) info.manifest = blobInfo[jss::manifest].asString(); } } - assert(result.size() == blobs.size()); + ASSERT( + result.size() == blobs.size(), + "ripple::ValidatorList::parseBlobs(version, Jason::Value) : " + "result size matches"); return result; } } @@ -442,7 +449,10 @@ ValidatorList::parseBlobs(protocol::TMValidatorListCollection const& body) info.manifest = blob.manifest(); } } - assert(result.size() == body.blobs_size()); + ASSERT( + result.size() == body.blobs_size(), + "ripple::ValidatorList::parseBlobs(TMValidatorList) : result size " + "match"); return result; } @@ -464,7 +474,7 @@ splitMessage( { if (begin == 0 && end == 0) end = largeMsg.blobs_size(); - assert(begin < end); + ASSERT(begin < end, "ripple::splitMessage : valid inputs"); if (end <= begin) return 0; @@ -498,7 +508,9 @@ splitMessageParts( if (blob.has_manifest()) smallMsg.set_manifest(blob.manifest()); - assert(Message::totalSize(smallMsg) <= maximiumMessageSize); + ASSERT( + Message::totalSize(smallMsg) <= maximiumMessageSize, + "ripple::splitMessageParts : maximum message size"); messages.emplace_back( std::make_shared(smallMsg, protocol::mtVALIDATORLIST), @@ -546,7 +558,10 @@ buildValidatorListMessage( ValidatorBlobInfo const& currentBlob, std::size_t maxSize) { - assert(messages.empty()); + ASSERT( + messages.empty(), + "ripple::buildValidatorListMessage(ValidatorBlobInfo) : empty messages " + "input"); protocol::TMValidatorList msg; auto const manifest = currentBlob.manifest ? *currentBlob.manifest : rawManifest; @@ -557,7 +572,10 @@ buildValidatorListMessage( // Override the version msg.set_version(version); - assert(Message::totalSize(msg) <= maximiumMessageSize); + ASSERT( + Message::totalSize(msg) <= maximiumMessageSize, + "ripple::buildValidatorListMessage(ValidatorBlobInfo) : maximum " + "message size"); messages.emplace_back( std::make_shared(msg, protocol::mtVALIDATORLIST), sha512Half(msg), @@ -576,7 +594,10 @@ buildValidatorListMessage( std::map const& blobInfos, std::size_t maxSize) { - assert(messages.empty()); + ASSERT( + messages.empty(), + "ripple::buildValidatorListMessage(std::map) : empty messages input"); protocol::TMValidatorListCollection msg; auto const version = rawVersion < 2 ? 2 : rawVersion; msg.set_version(version); @@ -592,7 +613,10 @@ buildValidatorListMessage( if (blobInfo.manifest) blob.set_manifest(*blobInfo.manifest); } - assert(msg.blobs_size() > 0); + ASSERT( + msg.blobs_size() > 0, + "ripple::buildValidatorListMessage(std::map) : minimum message blobs"); if (Message::totalSize(msg) > maxSize) { // split into smaller messages @@ -621,7 +645,10 @@ ValidatorList::buildValidatorListMessages( std::vector& messages, std::size_t maxSize /*= maximiumMessageSize*/) { - assert(!blobInfos.empty()); + ASSERT( + !blobInfos.empty(), + "ripple::ValidatorList::buildValidatorListMessages : empty messages " + "input"); auto const& [currentSeq, currentBlob] = *blobInfos.begin(); auto numVLs = std::accumulate( messages.begin(), @@ -704,7 +731,10 @@ ValidatorList::sendValidatorList( messages); if (newPeerSequence) { - assert(!messages.empty()); + ASSERT( + !messages.empty(), + "ripple::ValidatorList::sendValidatorList : non-empty messages " + "input"); // Don't send it next time. peer.setPublisherListSequence(publisherKey, newPeerSequence); @@ -720,7 +750,9 @@ ValidatorList::sendValidatorList( } // The only way sent wil be false is if the messages was too big, and // thus there will only be one entry without a message - assert(sent || messages.size() == 1); + ASSERT( + sent || messages.size() == 1, + "ripple::ValidatorList::sendValidatorList : sent or one message"); if (sent) { if (messageVersion > 1) @@ -734,7 +766,10 @@ ValidatorList::sendValidatorList( << "]"; else { - assert(numVLs == 1); + ASSERT( + numVLs == 1, + "ripple::ValidatorList::sendValidatorList : one validator " + "list"); JLOG(j.debug()) << "Sent validator list for " << strHex(publisherKey) << " with sequence " << newPeerSequence << " to " @@ -829,9 +864,10 @@ ValidatorList::broadcastBlobs( // be built to hold info for all of the valid VLs. std::map blobInfos; - assert( + ASSERT( lists.current.sequence == maxSequence || - lists.remaining.count(maxSequence) == 1); + lists.remaining.count(maxSequence) == 1, + "ripple::ValidatorList::broadcastBlobs : valid sequence"); // Can't use overlay.foreach here because we need to modify // the peer, and foreach provides a const& for (auto& peer : overlay.getActivePeers()) @@ -975,7 +1011,9 @@ ValidatorList::applyLists( for (auto iter = remaining.begin(); iter != remaining.end();) { auto next = std::next(iter); - assert(next == remaining.end() || next->first > iter->first); + ASSERT( + next == remaining.end() || next->first > iter->first, + "ripple::ValidatorList::applyLists : next is valid"); if (iter->first <= current.sequence || (next != remaining.end() && next->second.validFrom <= iter->second.validFrom)) @@ -1147,7 +1185,9 @@ ValidatorList::applyList( // Remove the entry in "remaining" pubCollection.remaining.erase(sequence); // Done - assert(publisher.sequence == sequence); + ASSERT( + publisher.sequence == sequence, + "ripple::ValidatorList::applyList : publisher sequence match"); } else { @@ -1441,9 +1481,10 @@ ValidatorList::removePublisherList( PublicKey const& publisherKey, PublisherStatus reason) { - assert( + ASSERT( reason != PublisherStatus::available && - reason != PublisherStatus::unavailable); + reason != PublisherStatus::unavailable, + "ripple::ValidatorList::removePublisherList : valid reason input"); auto const iList = publisherLists_.find(publisherKey); if (iList == publisherLists_.end()) return false; @@ -1628,7 +1669,9 @@ ValidatorList::getJson() const Json::Value& r = remaining.append(Json::objectValue); appendList(future, r); // Race conditions can happen, so make this check "fuzzy" - assert(future.validFrom > timeKeeper_.now() + 600s); + ASSERT( + future.validFrom > timeKeeper_.now() + 600s, + "ripple::ValidatorList::getJson : minimum valid from"); } if (remaining.size()) curr[jss::remaining] = std::move(remaining); @@ -1693,7 +1736,9 @@ ValidatorList::for_each_available( { if (plCollection.status != PublisherStatus::available) continue; - assert(plCollection.maxSequence); + ASSERT( + plCollection.maxSequence != 0, + "ripple::ValidatorList::for_each_available : nonzero maxSequence"); func( plCollection.rawManifest, plCollection.rawVersion, @@ -1827,21 +1872,31 @@ ValidatorList::updateTrusted( next->second.validFrom <= closeTime; ++iter, ++next) { - assert(std::next(iter) == next); + ASSERT( + std::next(iter) == next, + "ripple::ValidatorList::updateTrusted : sequential " + "remaining"); } - assert(iter != remaining.end()); + ASSERT( + iter != remaining.end(), + "ripple::ValidatorList::updateTrusted : non-end of " + "remaining"); // Rotate the pending list in to current auto sequence = iter->first; auto& candidate = iter->second; auto& current = collection.current; - assert(candidate.validFrom <= closeTime); + ASSERT( + candidate.validFrom <= closeTime, + "ripple::ValidatorList::updateTrusted : maximum time"); auto const oldList = current.list; current = std::move(candidate); if (collection.status != PublisherStatus::available) collection.status = PublisherStatus::available; - assert(current.sequence == sequence); + ASSERT( + current.sequence == sequence, + "ripple::ValidatorList::updateTrusted : sequence match"); // If the list is expired, remove the validators so they don't // get processed in. The expiration check below will do the rest // of the work @@ -1918,7 +1973,9 @@ ValidatorList::updateTrusted( { std::optional const signingKey = validatorManifests_.getSigningKey(k); - assert(signingKey); + ASSERT( + signingKey.has_value(), + "ripple::ValidatorList::updateTrusted : found signing key"); trustedSigningKeys_.insert(*signingKey); } } diff --git a/src/xrpld/app/misc/detail/ValidatorSite.cpp b/src/xrpld/app/misc/detail/ValidatorSite.cpp index 0c12816c1b8..fd775fc9251 100644 --- a/src/xrpld/app/misc/detail/ValidatorSite.cpp +++ b/src/xrpld/app/misc/detail/ValidatorSite.cpp @@ -411,7 +411,9 @@ ValidatorSite::parseJsonResponse( } auto const manifest = body[jss::manifest].asString(); - assert(version == body[jss::version].asUInt()); + ASSERT( + version == body[jss::version].asUInt(), + "ripple::ValidatorSite::parseJsonResponse : version match"); auto const& uri = sites_[siteIdx].activeResource->uri; auto const hash = sha512Half(manifest, blobs, version); auto const applyResult = app_.validators().applyListsAndBroadcast( @@ -586,7 +588,10 @@ ValidatorSite::onSiteFetch( case status::temporary_redirect: { auto newLocation = processRedirect(res, siteIdx, lock_sites); - assert(newLocation); + ASSERT( + newLocation != nullptr, + "ripple::ValidatorSite::onSiteFetch : non-null " + "validator"); // for perm redirects, also update our starting URI if (res.result() == status::moved_permanently || res.result() == status::permanent_redirect) diff --git a/src/xrpld/app/misc/detail/WorkBase.h b/src/xrpld/app/misc/detail/WorkBase.h index d7795af8bf0..8fece4703f5 100644 --- a/src/xrpld/app/misc/detail/WorkBase.h +++ b/src/xrpld/app/misc/detail/WorkBase.h @@ -282,7 +282,9 @@ WorkBase::onResponse(error_code const& ec) return fail(ec); close(); - assert(cb_); + ASSERT( + cb_ != nullptr, + "ripple::detail::WorkBase::onResponse : callback is set"); cb_(ec, lastEndpoint_, std::move(res_)); cb_ = nullptr; } diff --git a/src/xrpld/app/misc/detail/WorkFile.h b/src/xrpld/app/misc/detail/WorkFile.h index 266e5098cb6..1f08cacac68 100644 --- a/src/xrpld/app/misc/detail/WorkFile.h +++ b/src/xrpld/app/misc/detail/WorkFile.h @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include namespace ripple { @@ -88,7 +88,7 @@ WorkFile::run() error_code ec; auto const fileContents = getFileContents(ec, path_, megabytes(1)); - assert(cb_); + ASSERT(cb_ != nullptr, "ripple::detail::WorkFile::run : callback is set"); cb_(ec, fileContents); cb_ = nullptr; } diff --git a/src/xrpld/app/paths/Credit.cpp b/src/xrpld/app/paths/Credit.cpp index b3870937367..dbf0db45c4b 100644 --- a/src/xrpld/app/paths/Credit.cpp +++ b/src/xrpld/app/paths/Credit.cpp @@ -42,8 +42,12 @@ creditLimit( result.setIssuer(account); } - assert(result.getIssuer() == account); - assert(result.getCurrency() == currency); + ASSERT( + result.getIssuer() == account, + "ripple::creditLimit : result issuer match"); + ASSERT( + result.getCurrency() == currency, + "ripple::creditLimit : result currency match"); return result; } @@ -76,8 +80,12 @@ creditBalance( result.setIssuer(account); } - assert(result.getIssuer() == account); - assert(result.getCurrency() == currency); + ASSERT( + result.getIssuer() == account, + "ripple::creditBalance : result issuer match"); + ASSERT( + result.getCurrency() == currency, + "ripple::creditBalance : result currency match"); return result; } diff --git a/src/xrpld/app/paths/Flow.cpp b/src/xrpld/app/paths/Flow.cpp index c21d40c33b5..23d9da64150 100644 --- a/src/xrpld/app/paths/Flow.cpp +++ b/src/xrpld/app/paths/Flow.cpp @@ -193,7 +193,7 @@ flow( flowDebugInfo)); } - assert(!srcIsXRP && !dstIsXRP); + ASSERT(!srcIsXRP && !dstIsXRP, "ripple::flow : neither is XRP"); return finishFlow( sb, srcIssue, diff --git a/src/xrpld/app/paths/PathRequest.cpp b/src/xrpld/app/paths/PathRequest.cpp index bb6a104bca2..28ade441c2d 100644 --- a/src/xrpld/app/paths/PathRequest.cpp +++ b/src/xrpld/app/paths/PathRequest.cpp @@ -158,7 +158,7 @@ PathRequest::updateComplete() { std::lock_guard sl(mIndexLock); - assert(mInProgress); + ASSERT(mInProgress, "ripple::PathRequest::updateComplete : in progress"); mInProgress = false; if (fCompletion) diff --git a/src/xrpld/app/paths/Pathfinder.cpp b/src/xrpld/app/paths/Pathfinder.cpp index 5122bc7d6b8..3f506809887 100644 --- a/src/xrpld/app/paths/Pathfinder.cpp +++ b/src/xrpld/app/paths/Pathfinder.cpp @@ -189,7 +189,9 @@ Pathfinder::Pathfinder( , app_(app) , j_(app.journal("Pathfinder")) { - assert(!uSrcIssuer || isXRP(uSrcCurrency) == isXRP(uSrcIssuer.value())); + ASSERT( + !uSrcIssuer || isXRP(uSrcCurrency) == isXRP(uSrcIssuer.value()), + "ripple::Pathfinder::Pathfinder : valid inputs"); } bool @@ -577,7 +579,9 @@ Pathfinder::getBestPaths( if (mCompletePaths.empty() && extraPaths.empty()) return mCompletePaths; - assert(fullLiquidityPath.empty()); + ASSERT( + fullLiquidityPath.empty(), + "ripple::Pathfinder::getBestPaths : first empty path result"); const bool issuerIsSender = isXRP(mSrcCurrency) || (srcIssuer == mSrcAccount); @@ -638,7 +642,7 @@ Pathfinder::getBestPaths( if (path.empty()) { - assert(false); + UNREACHABLE("ripple::Pathfinder::getBestPaths : path not found"); continue; } @@ -681,7 +685,9 @@ Pathfinder::getBestPaths( if (remaining > beast::zero) { - assert(fullLiquidityPath.empty()); + ASSERT( + fullLiquidityPath.empty(), + "ripple::Pathfinder::getBestPaths : second empty path result"); JLOG(j_.info()) << "Paths could not send " << remaining << " of " << mDstAmount; } @@ -830,7 +836,9 @@ Pathfinder::addPathsForType( { case nt_SOURCE: // Source must always be at the start, so pathsOut has to be empty. - assert(pathsOut.empty()); + ASSERT( + pathsOut.empty(), + "ripple::Pathfinder::addPathsForType : empty paths"); pathsOut.push_back(STPath()); break; @@ -1282,7 +1290,7 @@ void fillPaths(Pathfinder::PaymentType type, PathCostList const& costs) { auto& list = mPathTable[type]; - assert(list.empty()); + ASSERT(list.empty(), "ripple::fillPaths : empty paths"); for (auto& cost : costs) list.push_back({cost.cost, makePath(cost.path)}); } diff --git a/src/xrpld/app/paths/RippleLineCache.cpp b/src/xrpld/app/paths/RippleLineCache.cpp index 0ff967c0821..053546ce0be 100644 --- a/src/xrpld/app/paths/RippleLineCache.cpp +++ b/src/xrpld/app/paths/RippleLineCache.cpp @@ -79,7 +79,9 @@ RippleLineCache::getRippleLines( // to be replaced by the full set. The full set will be built // below, and will be returned, if needed, on subsequent calls // for either value of outgoing. - assert(size <= totalLineCount_); + ASSERT( + size <= totalLineCount_, + "ripple::RippleLineCache::getRippleLines : maximum lines"); totalLineCount_ -= size; lines_.erase(otheriter); } @@ -99,7 +101,9 @@ RippleLineCache::getRippleLines( if (inserted) { - assert(it->second == nullptr); + ASSERT( + it->second == nullptr, + "ripple::RippleLineCache::getRippleLines : null lines"); auto lines = PathFindTrustLine::getItems(accountID, *ledger_, direction); if (lines.size()) @@ -110,7 +114,9 @@ RippleLineCache::getRippleLines( } } - assert(!it->second || (it->second->size() > 0)); + ASSERT( + !it->second || (it->second->size() > 0), + "ripple::RippleLineCache::getRippleLines : null or nonempty lines"); auto const size = it->second ? it->second->size() : 0; JLOG(journal_.trace()) << "getRippleLines for ledger " << ledger_->info().seq << " found " << size diff --git a/src/xrpld/app/paths/detail/AMMLiquidity.cpp b/src/xrpld/app/paths/detail/AMMLiquidity.cpp index 7b1649c649e..88600e2cc66 100644 --- a/src/xrpld/app/paths/detail/AMMLiquidity.cpp +++ b/src/xrpld/app/paths/detail/AMMLiquidity.cpp @@ -77,7 +77,9 @@ AMMLiquidity::generateFibSeqOffer( 196418, 317811, 514229, 832040, 1346269}; // clang-format on - assert(!ammContext_.maxItersReached()); + ASSERT( + !ammContext_.maxItersReached(), + "ripple::AMMLiquidity::generateFibSeqOffer : maximum iterations"); cur.out = toAmount( getIssue(balances.out), diff --git a/src/xrpld/app/paths/detail/AmountSpec.h b/src/xrpld/app/paths/detail/AmountSpec.h index 8a1117f9920..59ca5f5d29b 100644 --- a/src/xrpld/app/paths/detail/AmountSpec.h +++ b/src/xrpld/app/paths/detail/AmountSpec.h @@ -125,7 +125,7 @@ template <> inline IOUAmount& get(EitherAmount& amt) { - assert(!amt.native); + ASSERT(!amt.native, "ripple::get(EitherAmount&) : is not XRP"); return amt.iou; } @@ -133,7 +133,7 @@ template <> inline XRPAmount& get(EitherAmount& amt) { - assert(amt.native); + ASSERT(amt.native, "ripple::get(EitherAmount&) : is XRP"); return amt.xrp; } @@ -149,7 +149,9 @@ template <> inline IOUAmount const& get(EitherAmount const& amt) { - assert(!amt.native); + ASSERT( + !amt.native, + "ripple::get(EitherAmount const&) : is not XRP"); return amt.iou; } @@ -157,14 +159,16 @@ template <> inline XRPAmount const& get(EitherAmount const& amt) { - assert(amt.native); + ASSERT(amt.native, "ripple::get(EitherAmount const&) : is XRP"); return amt.xrp; } inline AmountSpec toAmountSpec(STAmount const& amt) { - assert(amt.mantissa() < std::numeric_limits::max()); + ASSERT( + amt.mantissa() < std::numeric_limits::max(), + "ripple::toAmountSpec(STAmount const&) : maximum mantissa"); bool const isNeg = amt.negative(); std::int64_t const sMant = isNeg ? -std::int64_t(amt.mantissa()) : amt.mantissa(); @@ -199,7 +203,10 @@ toAmountSpec(EitherAmount const& ea, std::optional const& c) AmountSpec r; r.native = (!c || isXRP(*c)); r.currency = c; - assert(ea.native == r.native); + ASSERT( + ea.native == r.native, + "ripple::toAmountSpec(EitherAmount const&&, std::optional) : " + "matching native"); if (r.native) { r.xrp = ea.xrp; diff --git a/src/xrpld/app/paths/detail/BookStep.cpp b/src/xrpld/app/paths/detail/BookStep.cpp index b22102119df..df05cc41864 100644 --- a/src/xrpld/app/paths/detail/BookStep.cpp +++ b/src/xrpld/app/paths/detail/BookStep.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -379,7 +380,9 @@ class BookOfferCrossingStep getQuality(std::optional const& limitQuality) { // It's really a programming error if the quality is missing. - assert(limitQuality); + ASSERT( + limitQuality.has_value(), + "ripple::BookOfferCrossingStep::getQuality : nonzero quality"); if (!limitQuality) Throw(tefINTERNAL, "Offer requires quality."); return *limitQuality; @@ -1107,7 +1110,7 @@ BookStep::revImp( // something went very wrong JLOG(j_.error()) << "BookStep remainingOut < 0 " << to_string(remainingOut); - assert(0); + UNREACHABLE("ripple::BookStep::revImp : remaining less than zero"); cache_.emplace(beast::zero, beast::zero); return {beast::zero, beast::zero}; } @@ -1130,7 +1133,7 @@ BookStep::fwdImp( boost::container::flat_set& ofrsToRm, TIn const& in) { - assert(cache_); + ASSERT(cache_.has_value(), "ripple::BookStep::fwdImp : cache is set"); TAmounts result(beast::zero, beast::zero); @@ -1149,7 +1152,9 @@ BookStep::fwdImp( TOut const& ownerGives, std::uint32_t transferRateIn, std::uint32_t transferRateOut) mutable -> bool { - assert(cache_); + ASSERT( + cache_.has_value(), + "ripple::BookStep::fwdImp::eachOffer : cache is set"); if (remainingIn <= beast::zero) return false; @@ -1277,7 +1282,7 @@ BookStep::fwdImp( // something went very wrong JLOG(j_.error()) << "BookStep remainingIn < 0 " << to_string(remainingIn); - assert(0); + UNREACHABLE("ripple::BookStep::fwdImp : remaining less than zero"); cache_.emplace(beast::zero, beast::zero); return {beast::zero, beast::zero}; } @@ -1412,7 +1417,7 @@ bookStepEqual(Step const& step, ripple::Book const& book) bool const outXRP = isXRP(book.out.currency); if (inXRP && outXRP) { - assert(0); + UNREACHABLE("ripple::test::bookStepEqual : no XRP to XRP book step"); return false; // no such thing as xrp/xrp book step } if (inXRP && !outXRP) diff --git a/src/xrpld/app/paths/detail/DirectStep.cpp b/src/xrpld/app/paths/detail/DirectStep.cpp index 7df06751140..194e77edc2c 100644 --- a/src/xrpld/app/paths/detail/DirectStep.cpp +++ b/src/xrpld/app/paths/detail/DirectStep.cpp @@ -514,7 +514,9 @@ DirectStepI::revImp( auto const [srcQOut, dstQIn] = qualities(sb, srcDebtDir, StrandDirection::reverse); - assert(static_cast(this)->verifyDstQualityIn(dstQIn)); + ASSERT( + static_cast(this)->verifyDstQualityIn(dstQIn), + "ripple::DirectStepI : valid destination quality"); Issue const srcToDstIss(currency_, redeems(srcDebtDir) ? dst_ : src_); @@ -633,7 +635,7 @@ DirectStepI::fwdImp( boost::container::flat_set& /*ofrsToRm*/, IOUAmount const& in) { - assert(cache_); + ASSERT(cache_.has_value(), "ripple::DirectStepI::fwdImp : cache is set"); auto const [maxSrcToDst, srcDebtDir] = static_cast(this)->maxFlow(sb, cache_->srcToDst); @@ -720,7 +722,7 @@ DirectStepI::validFwd( auto const savCache = *cache_; - assert(!in.native); + ASSERT(!in.native, "ripple::DirectStepI::validFwd : input is not XRP"); auto const [maxSrcToDst, srcDebtDir] = static_cast(this)->maxFlow(sb, cache_->srcToDst); @@ -784,8 +786,11 @@ DirectStepI::qualitiesSrcIssues( { // Charge a transfer rate when issuing and previous step redeems - assert(static_cast(this)->verifyPrevStepDebtDirection( - prevStepDebtDirection)); + ASSERT( + static_cast(this)->verifyPrevStepDebtDirection( + prevStepDebtDirection), + "ripple::DirectStepI::qualitiesSrcIssues : will prevStepDebtDirection " + "issue"); std::uint32_t const srcQOut = redeems(prevStepDebtDirection) ? transferRate(sb, src_).value @@ -924,7 +929,9 @@ DirectStepI::check(StrandContext const& ctx) const { if (!ctx.prevStep) { - assert(0); // prev seen book without a prev step!?! + UNREACHABLE( + "ripple::DirectStepI::check : prev seen book without a " + "prev step"); return temBAD_PATH_LOOP; } diff --git a/src/xrpld/app/paths/detail/FlowDebugInfo.h b/src/xrpld/app/paths/detail/FlowDebugInfo.h index 000db4e5714..38e1a8cff5e 100644 --- a/src/xrpld/app/paths/detail/FlowDebugInfo.h +++ b/src/xrpld/app/paths/detail/FlowDebugInfo.h @@ -89,7 +89,10 @@ struct FlowDebugInfo void pushLiquiditySrc(EitherAmount const& eIn, EitherAmount const& eOut) { - assert(!liquiditySrcIn.empty()); + ASSERT( + !liquiditySrcIn.empty(), + "ripple::path::detail::FlowDebugInfo::pushLiquiditySrc : " + "non-empty liquidity source"); liquiditySrcIn.back().push_back(eIn); liquiditySrcOut.back().push_back(eOut); } @@ -122,7 +125,9 @@ struct FlowDebugInfo auto i = timePoints.find(tag); if (i == timePoints.end()) { - assert(0); + UNREACHABLE( + "ripple::path::detail::FlowDebugInfo::duration : timepoint not " + "found"); return std::chrono::duration(0); } auto const& t = i->second; diff --git a/src/xrpld/app/paths/detail/PaySteps.cpp b/src/xrpld/app/paths/detail/PaySteps.cpp index f28c1b96a7c..56eae0aab3d 100644 --- a/src/xrpld/app/paths/detail/PaySteps.cpp +++ b/src/xrpld/app/paths/detail/PaySteps.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -100,13 +101,14 @@ toStep( // should already be taken care of JLOG(j.error()) << "Found offer/account payment step. Aborting payment strand."; - assert(0); + UNREACHABLE("ripple::toStep : offer/account payment payment strand"); return {temBAD_PATH, std::unique_ptr{}}; } - assert( + ASSERT( (e2->getNodeType() & STPathElement::typeCurrency) || - (e2->getNodeType() & STPathElement::typeIssuer)); + (e2->getNodeType() & STPathElement::typeIssuer), + "ripple::toStep : currency or issuer"); auto const outCurrency = e2->getNodeType() & STPathElement::typeCurrency ? e2->getCurrency() : curIssue.currency; @@ -120,7 +122,7 @@ toStep( return {temBAD_PATH, std::unique_ptr{}}; } - assert(e2->isOffer()); + ASSERT(e2->isOffer(), "ripple::toStep : is offer"); if (isXRP(outCurrency)) return make_BookStepIX(ctx, curIssue); @@ -391,7 +393,7 @@ toStrand( next->getCurrency() != curIssue.currency) { // Should never happen - assert(0); + UNREACHABLE("ripple::toStrand : offer currency mismatch"); return {temBAD_PATH, Strand{}}; } @@ -457,7 +459,7 @@ toStrand( if (!checkStrand()) { JLOG(j.warn()) << "Flow check strand failed"; - assert(0); + UNREACHABLE("ripple::toStrand : invalid strand"); return {temBAD_PATH, Strand{}}; } diff --git a/src/xrpld/app/paths/detail/StepChecks.h b/src/xrpld/app/paths/detail/StepChecks.h index 140c9d1fe46..3c1c883ebf6 100644 --- a/src/xrpld/app/paths/detail/StepChecks.h +++ b/src/xrpld/app/paths/detail/StepChecks.h @@ -35,7 +35,7 @@ checkFreeze( AccountID const& dst, Currency const& currency) { - assert(src != dst); + ASSERT(src != dst, "ripple::checkFreeze : unequal input accounts"); // check freeze if (auto sle = view.read(keylet::account(dst))) diff --git a/src/xrpld/app/paths/detail/StrandFlow.h b/src/xrpld/app/paths/detail/StrandFlow.h index 329a4cc643f..72ca97a42ac 100644 --- a/src/xrpld/app/paths/detail/StrandFlow.h +++ b/src/xrpld/app/paths/detail/StrandFlow.h @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -171,7 +172,9 @@ flow( << "Re-executed limiting step failed. r.first: " << to_string(get(r.first)) << " maxIn: " << to_string(*maxIn); - assert(0); + UNREACHABLE( + "ripple::flow : first step re-executing the " + "limiting step failed"); return Result{strand, std::move(ofrsToRm)}; } } @@ -207,7 +210,9 @@ flow( #else JLOG(j.fatal()) << "Re-executed limiting step failed"; #endif - assert(0); + UNREACHABLE( + "ripple::flow : limiting step re-executing the " + "limiting step failed"); return Result{strand, std::move(ofrsToRm)}; } } @@ -241,7 +246,9 @@ flow( #else JLOG(j.fatal()) << "Re-executed forward pass failed"; #endif - assert(0); + UNREACHABLE( + "ripple::flow : non-limiting step re-executing the " + "forward pass failed"); return Result{strand, std::move(ofrsToRm)}; } stepIn = r.second; @@ -493,7 +500,7 @@ class ActiveStrands { if (i >= cur_.size()) { - assert(0); + UNREACHABLE("ripple::ActiveStrands::get : input out of range"); return nullptr; } return cur_[i]; @@ -700,9 +707,10 @@ flow( flowDebugInfo->pushLiquiditySrc( EitherAmount(f.in), EitherAmount(f.out)); - assert( + ASSERT( f.out <= remainingOut && f.sandbox && - (!remainingIn || f.in <= *remainingIn)); + (!remainingIn || f.in <= *remainingIn), + "ripple::flow : remaining constraints"); Quality const q(f.out, f.in); @@ -725,7 +733,7 @@ flow( if (baseView.rules().enabled(featureFlowSortStrands)) { - assert(!best); + ASSERT(!best, "ripple::flow : best is unset"); if (!f.inactive) activeStrands.push(strand); best.emplace(f.in, f.out, std::move(*f.sandbox), *strand, q); @@ -839,7 +847,7 @@ flow( // running debug builds of rippled. While this issue still needs to // be resolved, the assert is causing more harm than good at this // point. - // assert(0); + // UNREACHABLE("ripple::flow : rounding error"); return {tefEXCEPTION, std::move(ofrsToRmOnFail)}; } @@ -876,7 +884,7 @@ flow( // Handles both cases 1. and 2. // fixFillOrKill amendment: // Handles 2. 1. is handled above and falls through for tfSell. - assert(remainingIn); + ASSERT(remainingIn.has_value(), "ripple::flow : nonzero remainingIn"); if (remainingIn && *remainingIn != beast::zero) return { tecPATH_PARTIAL, diff --git a/src/xrpld/app/paths/detail/XRPEndpointStep.cpp b/src/xrpld/app/paths/detail/XRPEndpointStep.cpp index ac178cbe2f2..ebc9510f4b2 100644 --- a/src/xrpld/app/paths/detail/XRPEndpointStep.cpp +++ b/src/xrpld/app/paths/detail/XRPEndpointStep.cpp @@ -281,7 +281,8 @@ XRPEndpointStep::fwdImp( boost::container::flat_set& ofrsToRm, XRPAmount const& in) { - assert(cache_); + ASSERT( + cache_.has_value(), "ripple::XRPEndpointStep::fwdImp : cache is set"); auto const balance = static_cast(this)->xrpLiquid(sb); auto const result = isLast_ ? in : std::min(balance, in); @@ -309,7 +310,7 @@ XRPEndpointStep::validFwd( return {false, EitherAmount(XRPAmount(beast::zero))}; } - assert(in.native); + ASSERT(in.native, "ripple::XRPEndpointStep::validFwd : input is XRP"); auto const& xrpIn = in.xrp; auto const balance = static_cast(this)->xrpLiquid(sb); diff --git a/src/xrpld/app/rdb/RelationalDatabase.h b/src/xrpld/app/rdb/RelationalDatabase.h index 5b06aa24d0e..a7528e2370d 100644 --- a/src/xrpld/app/rdb/RelationalDatabase.h +++ b/src/xrpld/app/rdb/RelationalDatabase.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -235,7 +236,7 @@ rangeCheckedCast(C c) c < std::numeric_limits::lowest())) { /* This should never happen */ - assert(0); + UNREACHABLE("ripple::rangeCheckedCast : domain error"); JLOG(debugLog().error()) << "rangeCheckedCast domain error:" << " value = " << c << " min = " << std::numeric_limits::lowest() diff --git a/src/xrpld/app/rdb/backend/detail/Node.cpp b/src/xrpld/app/rdb/backend/detail/Node.cpp index 2ea6bd12c62..cd7bab3782a 100644 --- a/src/xrpld/app/rdb/backend/detail/Node.cpp +++ b/src/xrpld/app/rdb/backend/detail/Node.cpp @@ -58,7 +58,7 @@ to_string(TableType type) case TableType::AccountTransactions: return "AccountTransactions"; default: - assert(false); + UNREACHABLE("ripple::detail::to_string : invalid TableType"); return "Unknown"; } } @@ -202,7 +202,7 @@ saveValidatedLedger( if (!ledger->info().accountHash.isNonZero()) { JLOG(j.fatal()) << "AH is zero: " << getJson({*ledger, {}}); - assert(false); + UNREACHABLE("ripple::detail::saveValidatedLedger : zero account hash"); } if (ledger->info().accountHash != ledger->stateMap().getHash().as_uint256()) @@ -211,10 +211,13 @@ saveValidatedLedger( << " != " << ledger->stateMap().getHash(); JLOG(j.fatal()) << "saveAcceptedLedger: seq=" << seq << ", current=" << current; - assert(false); + UNREACHABLE( + "ripple::detail::saveValidatedLedger : mismatched account hash"); } - assert(ledger->info().txHash == ledger->txMap().getHash().as_uint256()); + ASSERT( + ledger->info().txHash == ledger->txMap().getHash().as_uint256(), + "ripple::detail::saveValidatedLedger : transaction hash match"); // Save the ledger header in the hashed object store { diff --git a/src/xrpld/app/rdb/detail/Vacuum.cpp b/src/xrpld/app/rdb/detail/Vacuum.cpp index cc7f01a8409..10bd95177ed 100644 --- a/src/xrpld/app/rdb/detail/Vacuum.cpp +++ b/src/xrpld/app/rdb/detail/Vacuum.cpp @@ -28,7 +28,9 @@ doVacuumDB(DatabaseCon::Setup const& setup, beast::Journal j) boost::filesystem::path dbPath = setup.dataDir / TxDBName; uintmax_t const dbSize = file_size(dbPath); - assert(dbSize != static_cast(-1)); + ASSERT( + dbSize != static_cast(-1), + "ripple:doVacuumDB : file_size succeeded"); if (auto available = space(dbPath.parent_path()).available; available < dbSize) @@ -54,7 +56,9 @@ doVacuumDB(DatabaseCon::Setup const& setup, beast::Journal j) std::cout << "VACUUM beginning. page_size: " << pageSize << std::endl; session << "VACUUM;"; - assert(setup.globalPragma); + ASSERT( + setup.globalPragma != nullptr, + "ripple:doVacuumDB : non-null global pragma"); for (auto const& p : *setup.globalPragma) session << p; session << "PRAGMA page_size;", soci::into(pageSize); diff --git a/src/xrpld/app/tx/detail/AMMBid.cpp b/src/xrpld/app/tx/detail/AMMBid.cpp index 9de3762d2e3..29ac826a5de 100644 --- a/src/xrpld/app/tx/detail/AMMBid.cpp +++ b/src/xrpld/app/tx/detail/AMMBid.cpp @@ -181,7 +181,9 @@ applyBid( } else { - assert(ammSle->isFieldPresent(sfAuctionSlot)); + ASSERT( + ammSle->isFieldPresent(sfAuctionSlot), + "ripple::applyBid : has auction slot"); if (!ammSle->isFieldPresent(sfAuctionSlot)) return {tecINTERNAL, false}; } @@ -304,7 +306,7 @@ applyBid( { // Price the slot was purchased at. STAmount const pricePurchased = auctionSlot[sfPrice]; - assert(timeSlot); + ASSERT(timeSlot.has_value(), "ripple::applyBid : timeSlot is set"); auto const fractionUsed = (Number(*timeSlot) + 1) / AUCTION_SLOT_TIME_INTERVALS; auto const fractionRemaining = Number(1) - fractionUsed; diff --git a/src/xrpld/app/tx/detail/AMMDeposit.cpp b/src/xrpld/app/tx/detail/AMMDeposit.cpp index 3448401eb79..21d48d42c9a 100644 --- a/src/xrpld/app/tx/detail/AMMDeposit.cpp +++ b/src/xrpld/app/tx/detail/AMMDeposit.cpp @@ -466,7 +466,9 @@ AMMDeposit::applyGuts(Sandbox& sb) if (result == tesSUCCESS) { - assert(newLPTokenBalance > beast::zero); + ASSERT( + newLPTokenBalance > beast::zero, + "ripple::AMMDeposit::applyGuts : valid new LP token balance"); ammSle->setFieldAmount(sfLPTokenBalance, newLPTokenBalance); // LP depositing into AMM empty state gets the auction slot // and the voting diff --git a/src/xrpld/app/tx/detail/AMMVote.cpp b/src/xrpld/app/tx/detail/AMMVote.cpp index c4b6c612c63..1269bf4c383 100644 --- a/src/xrpld/app/tx/detail/AMMVote.cpp +++ b/src/xrpld/app/tx/detail/AMMVote.cpp @@ -200,9 +200,10 @@ applyVote( } } - assert( + ASSERT( !ctx_.view().rules().enabled(fixInnerObjTemplate) || - ammSle->isFieldPresent(sfAuctionSlot)); + ammSle->isFieldPresent(sfAuctionSlot), + "ripple::applyVote : has auction slot"); // Update the vote entries and the trading/discounted fee. ammSle->setFieldArray(sfVoteSlots, updatedVoteSlots); diff --git a/src/xrpld/app/tx/detail/AMMWithdraw.cpp b/src/xrpld/app/tx/detail/AMMWithdraw.cpp index 118262905c1..d1cfebe0639 100644 --- a/src/xrpld/app/tx/detail/AMMWithdraw.cpp +++ b/src/xrpld/app/tx/detail/AMMWithdraw.cpp @@ -877,7 +877,9 @@ AMMWithdraw::equalWithdrawLimit( frac = Number{amount2} / amount2Balance; auto const amountWithdraw = amountBalance * frac; - assert(amountWithdraw <= amount); + ASSERT( + amountWithdraw <= amount, + "ripple::AMMWithdraw::equalWithdrawLimit : maximum amountWithdraw"); return withdraw( view, ammSle, diff --git a/src/xrpld/app/tx/detail/ApplyContext.cpp b/src/xrpld/app/tx/detail/ApplyContext.cpp index 969af7960eb..925da7aaf48 100644 --- a/src/xrpld/app/tx/detail/ApplyContext.cpp +++ b/src/xrpld/app/tx/detail/ApplyContext.cpp @@ -21,10 +21,10 @@ #include #include #include +#include #include #include #include -#include namespace ripple { @@ -146,7 +146,9 @@ ApplyContext::checkInvariantsHelper( TER ApplyContext::checkInvariants(TER const result, XRPAmount const fee) { - assert(isTesSuccess(result) || isTecClaim(result)); + ASSERT( + isTesSuccess(result) || isTecClaim(result), + "ripple::ApplyContext::checkInvariants : is tesSUCCESS or tecCLAIM"); return checkInvariantsHelper( result, diff --git a/src/xrpld/app/tx/detail/Change.cpp b/src/xrpld/app/tx/detail/Change.cpp index 909f35fc799..d2772d6966e 100644 --- a/src/xrpld/app/tx/detail/Change.cpp +++ b/src/xrpld/app/tx/detail/Change.cpp @@ -149,7 +149,7 @@ Change::doApply() case ttUNL_MODIFY: return applyUNLModify(); default: - assert(0); + UNREACHABLE("ripple::Change::doApply : invalid transaction type"); return tefFAILURE; } } @@ -157,7 +157,8 @@ Change::doApply() void Change::preCompute() { - assert(account_ == beast::zero); + ASSERT( + account_ == beast::zero, "ripple::Change::preCompute : zero account"); } void diff --git a/src/xrpld/app/tx/detail/CreateOffer.cpp b/src/xrpld/app/tx/detail/CreateOffer.cpp index 2a5145594a1..578600621f2 100644 --- a/src/xrpld/app/tx/detail/CreateOffer.cpp +++ b/src/xrpld/app/tx/detail/CreateOffer.cpp @@ -210,7 +210,9 @@ CreateOffer::checkAcceptAsset( Issue const& issue) { // Only valid for custom currencies - assert(!isXRP(issue.currency)); + ASSERT( + !isXRP(issue.currency), + "ripple::CreateOffer::checkAcceptAsset : input is not XRP"); auto const issuerAccount = view.read(keylet::account(issue.account)); @@ -283,7 +285,9 @@ CreateOffer::select_path( OfferStream const& leg2) { // If we don't have any viable path, why are we here?! - assert(have_direct || have_bridge); + ASSERT( + have_direct || have_bridge, + "ripple::CreateOffer::select_path : valid inputs"); // If there's no bridged path, the direct is the best by default. if (!have_bridge) @@ -327,7 +331,9 @@ CreateOffer::bridged_cross( { auto const& takerAmount = taker.original_offer(); - assert(!isXRP(takerAmount.in) && !isXRP(takerAmount.out)); + ASSERT( + !isXRP(takerAmount.in) && !isXRP(takerAmount.out), + "ripple::CreateOffer::bridged_cross : neither is XRP"); if (isXRP(takerAmount.in) || isXRP(takerAmount.out)) Throw("Bridging with XRP and an endpoint."); @@ -497,7 +503,9 @@ CreateOffer::bridged_cross( // Postcondition: If we aren't done, then we *must* have consumed at // least one offer fully. - assert(direct_consumed || leg1_consumed || leg2_consumed); + ASSERT( + direct_consumed || leg1_consumed || leg2_consumed, + "ripple::CreateOffer::bridged_cross : consumed an offer"); if (!direct_consumed && !leg1_consumed && !leg2_consumed) Throw( @@ -587,7 +595,9 @@ CreateOffer::direct_cross( // Postcondition: If we aren't done, then we *must* have consumed the // offer on the books fully! - assert(direct_consumed); + ASSERT( + direct_consumed, + "ripple::CreateOffer::direct_cross : consumed an offer"); if (!direct_consumed) Throw( @@ -849,7 +859,9 @@ CreateOffer::flowCross( // remaining output. This too preserves the offer // Quality. afterCross.out -= result.actualAmountOut; - assert(afterCross.out >= beast::zero); + ASSERT( + afterCross.out >= beast::zero, + "ripple::CreateOffer::flowCross : minimum offer"); if (afterCross.out < beast::zero) afterCross.out.clear(); afterCross.in = mulRound( @@ -1046,7 +1058,10 @@ CreateOffer::applyGuts(Sandbox& sb, Sandbox& sbCancel) // We expect the implementation of cross to succeed // or give a tec. - assert(result == tesSUCCESS || isTecClaim(result)); + ASSERT( + result == tesSUCCESS || isTecClaim(result), + "ripple::CreateOffer::applyGuts : result is tesSUCCESS or " + "tecCLAIM"); if (auto stream = j_.trace()) { @@ -1064,8 +1079,12 @@ CreateOffer::applyGuts(Sandbox& sb, Sandbox& sbCancel) return {result, true}; } - assert(saTakerGets.issue() == place_offer.in.issue()); - assert(saTakerPays.issue() == place_offer.out.issue()); + ASSERT( + saTakerGets.issue() == place_offer.in.issue(), + "ripple::CreateOffer::applyGuts : taker gets issue match"); + ASSERT( + saTakerPays.issue() == place_offer.out.issue(), + "ripple::CreateOffer::applyGuts : taker pays issue match"); if (takerAmount != place_offer) crossed = true; @@ -1093,7 +1112,9 @@ CreateOffer::applyGuts(Sandbox& sb, Sandbox& sbCancel) saTakerGets = place_offer.in; } - assert(saTakerPays > zero && saTakerGets > zero); + ASSERT( + saTakerPays > zero && saTakerGets > zero, + "ripple::CreateOffer::applyGuts : taker pays and gets positive"); if (result != tesSUCCESS) { diff --git a/src/xrpld/app/tx/detail/DeleteAccount.cpp b/src/xrpld/app/tx/detail/DeleteAccount.cpp index a7f33a3d8dd..44addd3de52 100644 --- a/src/xrpld/app/tx/detail/DeleteAccount.cpp +++ b/src/xrpld/app/tx/detail/DeleteAccount.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -242,7 +243,9 @@ DeleteAccount::preclaim(PreclaimContext const& ctx) } auto sleAccount = ctx.view.read(keylet::account(account)); - assert(sleAccount); + ASSERT( + sleAccount != nullptr, + "ripple::DeleteAccount::preclaim : non-null account"); if (!sleAccount) return terNO_ACCOUNT; @@ -345,11 +348,15 @@ TER DeleteAccount::doApply() { auto src = view().peek(keylet::account(account_)); - assert(src); + ASSERT( + src != nullptr, + "ripple::DeleteAccount::doApply : non-null source account"); auto const dstID = ctx_.tx[sfDestination]; auto dst = view().peek(keylet::account(dstID)); - assert(dst); + ASSERT( + dst != nullptr, + "ripple::DeleteAccount::doApply : non-null destination account"); if (!src || !dst) return tefBAD_LEDGER; @@ -377,7 +384,9 @@ DeleteAccount::doApply() return {result, SkipEntry::No}; } - assert(!"Undeletable entry should be found in preclaim."); + UNREACHABLE( + "ripple::DeleteAccount::doApply : undeletable item not found " + "in preclaim"); JLOG(j_.error()) << "DeleteAccount undeletable item not " "found in preclaim."; return {tecHAS_OBLIGATIONS, SkipEntry::No}; @@ -391,7 +400,9 @@ DeleteAccount::doApply() (*src)[sfBalance] = (*src)[sfBalance] - mSourceBalance; ctx_.deliver(mSourceBalance); - assert((*src)[sfBalance] == XRPAmount(0)); + ASSERT( + (*src)[sfBalance] == XRPAmount(0), + "ripple::DeleteAccount::doApply : source balance is zero"); // If there's still an owner directory associated with the source account // delete it. diff --git a/src/xrpld/app/tx/detail/InvariantCheck.cpp b/src/xrpld/app/tx/detail/InvariantCheck.cpp index 90fc399b344..5101eba60aa 100644 --- a/src/xrpld/app/tx/detail/InvariantCheck.cpp +++ b/src/xrpld/app/tx/detail/InvariantCheck.cpp @@ -381,7 +381,8 @@ AccountRootsDeletedClean::finalize( // transaction processing results, however unlikely, only fail if the // feature is enabled. Enabled, or not, though, a fatal-level message will // be logged - bool const enforce = view.rules().enabled(featureInvariantsV1_1); + [[maybe_unused]] bool const enforce = + view.rules().enabled(featureInvariantsV1_1); auto const objectExists = [&view, enforce, &j](auto const& keylet) { if (auto const sle = view.read(keylet)) @@ -399,8 +400,10 @@ AccountRootsDeletedClean::finalize( JLOG(j.fatal()) << "Invariant failed: account deletion left behind a " << typeName << " object"; - (void)enforce; - assert(enforce); + ASSERT( + enforce, + "ripple::AccountRootsDeletedClean::finalize::objectExists : " + "account deletion left no objects behind"); return true; } return false; diff --git a/src/xrpld/app/tx/detail/NFTokenMint.cpp b/src/xrpld/app/tx/detail/NFTokenMint.cpp index d5c3a8707c2..b903563dff7 100644 --- a/src/xrpld/app/tx/detail/NFTokenMint.cpp +++ b/src/xrpld/app/tx/detail/NFTokenMint.cpp @@ -160,7 +160,9 @@ NFTokenMint::createNFTokenID( std::memcpy(ptr, &tokenSeq, sizeof(tokenSeq)); ptr += sizeof(tokenSeq); - assert(std::distance(buf.data(), ptr) == buf.size()); + ASSERT( + std::distance(buf.data(), ptr) == buf.size(), + "ripple::NFTokenMint::createNFTokenID : data size matches the buffer"); return uint256::fromVoid(buf.data()); } diff --git a/src/xrpld/app/tx/detail/NFTokenUtils.cpp b/src/xrpld/app/tx/detail/NFTokenUtils.cpp index 61ff8e200b3..38378b7ff9e 100644 --- a/src/xrpld/app/tx/detail/NFTokenUtils.cpp +++ b/src/xrpld/app/tx/detail/NFTokenUtils.cpp @@ -191,7 +191,9 @@ getPageForToken( : carr[0].getFieldH256(sfNFTokenID); auto np = std::make_shared(keylet::nftpage(base, tokenIDForNewPage)); - assert(np->key() > base.key); + ASSERT( + np->key() > base.key, + "ripple::nft::getPageForToken : valid NFT page index"); np->setFieldArray(sfNFTokens, narr); np->setFieldH256(sfNextPageMin, cp->key()); @@ -243,7 +245,9 @@ compareTokens(uint256 const& a, uint256 const& b) TER insertToken(ApplyView& view, AccountID owner, STObject&& nft) { - assert(nft.isFieldPresent(sfNFTokenID)); + ASSERT( + nft.isFieldPresent(sfNFTokenID), + "ripple::nft::insertToken : has NFT token"); // First, we need to locate the page the NFT belongs to, creating it // if necessary. This operation may fail if it is impossible to insert @@ -783,7 +787,9 @@ repairNFTokenDirectoryLinks(ApplyView& view, AccountID const& owner) return didRepair; } - assert(nextPage); + ASSERT( + nextPage != nullptr, + "ripple::nft::repairNFTokenDirectoryLinks : next page is available"); if (nextPage->isFieldPresent(sfNextPageMin)) { didRepair = true; @@ -891,7 +897,9 @@ tokenOfferCreatePreclaim( if (nftIssuer != acctID && !(nftFlags & nft::flagTransferable)) { auto const root = view.read(keylet::account(nftIssuer)); - assert(root); + ASSERT( + root != nullptr, + "ripple::nft::tokenOfferCreatePreclaim : non-null account"); if (auto minter = (*root)[~sfNFTokenMinter]; minter != acctID) return tefNFTOKEN_IS_NOT_TRANSFERABLE; diff --git a/src/xrpld/app/tx/detail/Offer.h b/src/xrpld/app/tx/detail/Offer.h index a6f707ba561..23129952c3d 100644 --- a/src/xrpld/app/tx/detail/Offer.h +++ b/src/xrpld/app/tx/detail/Offer.h @@ -209,7 +209,7 @@ void TOffer::setFieldAmounts() { #ifdef _MSC_VER - assert(0); + UNREACHABLE("ripple::TOffer::setFieldAmounts : must be specialized"); #else static_assert(sizeof(TOut) == -1, "Must be specialized"); #endif diff --git a/src/xrpld/app/tx/detail/OfferStream.cpp b/src/xrpld/app/tx/detail/OfferStream.cpp index b963195259a..2fb9ad6a143 100644 --- a/src/xrpld/app/tx/detail/OfferStream.cpp +++ b/src/xrpld/app/tx/detail/OfferStream.cpp @@ -51,7 +51,8 @@ TOfferStreamBase::TOfferStreamBase( , tip_(view, book_) , counter_(counter) { - assert(validBook_); + ASSERT( + validBook_, "ripple::TOfferStreamBase::TOfferStreamBase : valid book"); } // Handle the case where a directory item with no corresponding ledger entry @@ -339,7 +340,9 @@ TOfferStreamBase::step() std::is_same_v)) return shouldRmSmallIncreasedQOffer(); } - assert(0); // xrp/xrp offer!?! should never happen + UNREACHABLE( + "rippls::TOfferStreamBase::step::rmSmallIncreasedQOffer : XRP " + "vs XRP offer"); return false; }(); diff --git a/src/xrpld/app/tx/detail/PayChan.cpp b/src/xrpld/app/tx/detail/PayChan.cpp index b2d4c0c9449..c313feff43f 100644 --- a/src/xrpld/app/tx/detail/PayChan.cpp +++ b/src/xrpld/app/tx/detail/PayChan.cpp @@ -150,7 +150,9 @@ closeChannel( if (!sle) return tefINTERNAL; - assert((*slep)[sfAmount] >= (*slep)[sfBalance]); + ASSERT( + (*slep)[sfAmount] >= (*slep)[sfBalance], + "ripple::closeChannel : minimum channel amount"); (*sle)[sfBalance] = (*sle)[sfBalance] + (*slep)[sfAmount] - (*slep)[sfBalance]; adjustOwnerCount(view, sle, -1, j); @@ -546,7 +548,9 @@ PayChanClaim::doApply() (*slep)[sfBalance] = ctx_.tx[sfBalance]; XRPAmount const reqDelta = reqBalance - chanBalance; - assert(reqDelta >= beast::zero); + ASSERT( + reqDelta >= beast::zero, + "ripple::PayChanClaim::doApply : minimum balance delta"); (*sled)[sfBalance] = (*sled)[sfBalance] + reqDelta; ctx_.view().update(sled); ctx_.view().update(slep); diff --git a/src/xrpld/app/tx/detail/Payment.cpp b/src/xrpld/app/tx/detail/Payment.cpp index 2be784306cd..d6f7c60fabc 100644 --- a/src/xrpld/app/tx/detail/Payment.cpp +++ b/src/xrpld/app/tx/detail/Payment.cpp @@ -525,7 +525,7 @@ Payment::doApply() return res; } - assert(dstAmount.native()); + ASSERT(dstAmount.native(), "ripple::Payment::doApply : amount is XRP"); // Direct XRP payment. diff --git a/src/xrpld/app/tx/detail/SetSignerList.cpp b/src/xrpld/app/tx/detail/SetSignerList.cpp index 0949fbbe775..9c4fcd0e6c1 100644 --- a/src/xrpld/app/tx/detail/SetSignerList.cpp +++ b/src/xrpld/app/tx/detail/SetSignerList.cpp @@ -128,7 +128,7 @@ SetSignerList::doApply() default: break; } - assert(false); // Should not be possible to get here. + UNREACHABLE("ripple::SetSignerList::doApply : invalid operation"); return temMALFORMED; } @@ -137,8 +137,12 @@ SetSignerList::preCompute() { // Get the quorum and operation info. auto result = determineOperation(ctx_.tx, view().flags(), j_); - assert(std::get<0>(result) == tesSUCCESS); - assert(std::get<3>(result) != unknown); + ASSERT( + std::get<0>(result) == tesSUCCESS, + "ripple::SetSignerList::preCompute : result is tesSUCCESS"); + ASSERT( + std::get<3>(result) != unknown, + "ripple::SetSignerList::preCompute : result is known operation"); quorum_ = std::get<1>(result); signers_ = std::get<2>(result); @@ -171,8 +175,12 @@ signerCountBasedOwnerCountDelta(std::size_t entryCount, Rules const& rules) // The static_cast should always be safe since entryCount should always // be in the range from 1 to 8 (or 32 if ExpandedSignerList is enabled). // We've got a lot of room to grow. - assert(entryCount >= STTx::minMultiSigners); - assert(entryCount <= STTx::maxMultiSigners(&rules)); + ASSERT( + entryCount >= STTx::minMultiSigners, + "ripple::signerCountBasedOwnerCountDelta : minimum signers"); + ASSERT( + entryCount <= STTx::maxMultiSigners(&rules), + "ripple::signerCountBasedOwnerCountDelta : maximum signers"); return 2 + static_cast(entryCount); } @@ -260,7 +268,10 @@ SetSignerList::validateQuorumAndSignerEntries( } // Make sure there are no duplicate signers. - assert(std::is_sorted(signers.begin(), signers.end())); + ASSERT( + std::is_sorted(signers.begin(), signers.end()), + "ripple::SetSignerList::validateQuorumAndSignerEntries : sorted " + "signers"); if (std::adjacent_find(signers.begin(), signers.end()) != signers.end()) { JLOG(j.trace()) << "Duplicate signers in signer list"; diff --git a/src/xrpld/app/tx/detail/Taker.cpp b/src/xrpld/app/tx/detail/Taker.cpp index 9d335de2846..6e4b7f5cd57 100644 --- a/src/xrpld/app/tx/detail/Taker.cpp +++ b/src/xrpld/app/tx/detail/Taker.cpp @@ -54,24 +54,36 @@ BasicTaker::BasicTaker( , cross_type_(cross_type) , journal_(journal) { - assert(remaining_.in > beast::zero); - assert(remaining_.out > beast::zero); - - assert(m_rate_in.value != 0); - assert(m_rate_out.value != 0); + ASSERT( + remaining_.in > beast::zero, + "ripple::BasicTaker::BasicTaker : positive remaining in"); + ASSERT( + remaining_.out > beast::zero, + "ripple::BasicTaker::BasicTaker : positive remaining out"); + + ASSERT( + m_rate_in.value != 0, + "ripple::BasicTaker::BasicTaker : nonzero rate in"); + ASSERT( + m_rate_out.value != 0, + "ripple::BasicTaker::BasicTaker : nonzero rate out"); // If we are dealing with a particular flavor, make sure that it's the // flavor we expect: - assert( + ASSERT( cross_type != CrossType::XrpToIou || - (isXRP(issue_in()) && !isXRP(issue_out()))); + (isXRP(issue_in()) && !isXRP(issue_out())), + "ripple::BasicTaker::BasicTaker : valid cross to IOU"); - assert( + ASSERT( cross_type != CrossType::IouToXrp || - (!isXRP(issue_in()) && isXRP(issue_out()))); + (!isXRP(issue_in()) && isXRP(issue_out())), + "ripple::BasicTaker::BasicTaker : valid cross to XRP"); // And make sure we're not crossing XRP for XRP - assert(!isXRP(issue_in()) || !isXRP(issue_out())); + ASSERT( + !isXRP(issue_in()) || !isXRP(issue_out()), + "ripple::BasicTaker::BasicTaker : not crossing XRP for XRP"); // If this is a passive order, we adjust the quality so as to prevent offers // at the same quality level from being consumed. @@ -150,7 +162,9 @@ BasicTaker::remaining_offer() const if (sell_) { - assert(remaining_.in > beast::zero); + ASSERT( + remaining_.in > beast::zero, + "ripple::BasicTaker::remaining_offer : positive remaining in"); // We scale the output based on the remaining input: return Amounts( @@ -158,7 +172,9 @@ BasicTaker::remaining_offer() const divRound(remaining_.in, quality_.rate(), issue_out_, true)); } - assert(remaining_.out > beast::zero); + ASSERT( + remaining_.out > beast::zero, + "ripple::BasicTaker::remaining_offer : positive remaining out"); // We scale the input based on the remaining output: return Amounts( @@ -424,7 +440,9 @@ BasicTaker::do_cross(Amounts offer, Quality quality, AccountID const& owner) remaining_.out -= result.order.out; remaining_.in -= result.order.in; - assert(remaining_.in >= beast::zero); + ASSERT( + remaining_.in >= beast::zero, + "ripple::BasicTaker::do_cross : minimum remaining in"); return result; } @@ -439,10 +457,17 @@ BasicTaker::do_cross( Quality quality2, AccountID const& owner2) { - assert(!offer1.in.native()); - assert(offer1.out.native()); - assert(offer2.in.native()); - assert(!offer2.out.native()); + ASSERT( + !offer1.in.native(), + "ripple::BasicTaker::do_cross : offer1 in is not XRP"); + ASSERT( + offer1.out.native(), + "ripple::BasicTaker::do_cross : offer1 out is XRP"); + ASSERT( + offer2.in.native(), "ripple::BasicTaker::do_cross : offer2 in is XRP"); + ASSERT( + !offer2.out.native(), + "ripple::BasicTaker::do_cross : offer2 out is not XRP"); // If the taker owns the first leg of the offer, then the taker's available // funds aren't the limiting factor for the input - the offer itself is. @@ -559,8 +584,12 @@ Taker::Taker( , direct_crossings_(0) , bridge_crossings_(0) { - assert(issue_in() == offer.in.issue()); - assert(issue_out() == offer.out.issue()); + ASSERT( + issue_in() == offer.in.issue(), + "ripple::Taker::Taker : issue in is a match"); + ASSERT( + issue_out() == offer.out.issue(), + "ripple::Taker::Taker : issue out is a match"); if (auto stream = journal_.debug()) { @@ -689,7 +718,8 @@ Taker::fill(BasicTaker::Flow const& flow, Offer& offer) if (cross_type() != CrossType::XrpToIou) { - assert(!isXRP(flow.order.in)); + ASSERT( + !isXRP(flow.order.in), "ripple::Taker::fill : order in is not XRP"); if (result == tesSUCCESS) result = @@ -701,7 +731,7 @@ Taker::fill(BasicTaker::Flow const& flow, Offer& offer) } else { - assert(isXRP(flow.order.in)); + ASSERT(isXRP(flow.order.in), "ripple::Taker::fill : order in is XRP"); if (result == tesSUCCESS) result = transferXRP(account(), offer.owner(), flow.order.in); @@ -710,7 +740,9 @@ Taker::fill(BasicTaker::Flow const& flow, Offer& offer) // Now send funds from the account whose offer we're taking if (cross_type() != CrossType::IouToXrp) { - assert(!isXRP(flow.order.out)); + ASSERT( + !isXRP(flow.order.out), + "ripple::Taker::fill : order out is not XRP"); if (result == tesSUCCESS) result = redeemIOU( @@ -722,7 +754,7 @@ Taker::fill(BasicTaker::Flow const& flow, Offer& offer) } else { - assert(isXRP(flow.order.out)); + ASSERT(isXRP(flow.order.out), "ripple::Taker::fill : order out is XRP"); if (result == tesSUCCESS) result = transferXRP(offer.owner(), account(), flow.order.out); diff --git a/src/xrpld/app/tx/detail/Transactor.cpp b/src/xrpld/app/tx/detail/Transactor.cpp index 052a735a2fd..8352dbc7800 100644 --- a/src/xrpld/app/tx/detail/Transactor.cpp +++ b/src/xrpld/app/tx/detail/Transactor.cpp @@ -368,7 +368,9 @@ Transactor::checkPriorTxAndLastLedger(PreclaimContext const& ctx) TER Transactor::consumeSeqProxy(SLE::pointer const& sleAccount) { - assert(sleAccount); + ASSERT( + sleAccount != nullptr, + "ripple::Transactor::consumeSeqProxy : non-null account"); SeqProxy const seqProx = ctx_.tx.getSeqProxy(); if (seqProx.isSeq()) { @@ -440,7 +442,9 @@ Transactor::ticketDelete( void Transactor::preCompute() { - assert(account_ != beast::zero); + ASSERT( + account_ != beast::zero, + "ripple::Transactor::preCompute : nonzero account"); } TER @@ -454,7 +458,9 @@ Transactor::apply() // sle must exist except for transactions // that allow zero account. - assert(sle != nullptr || account_ == beast::zero); + ASSERT( + sle != nullptr || account_ == beast::zero, + "ripple::Transactor::apply : non-null SLE or zero account"); if (sle) { @@ -579,8 +585,12 @@ Transactor::checkMultiSign(PreclaimContext const& ctx) // We have plans to support multiple SignerLists in the future. The // presence and defaulted value of the SignerListID field will enable that. - assert(sleAccountSigners->isFieldPresent(sfSignerListID)); - assert(sleAccountSigners->getFieldU32(sfSignerListID) == 0); + ASSERT( + sleAccountSigners->isFieldPresent(sfSignerListID), + "ripple::Transactor::checkMultiSign : has signer list ID"); + ASSERT( + sleAccountSigners->getFieldU32(sfSignerListID) == 0, + "ripple::Transactor::checkMultiSign : signer list ID is 0"); auto accountSigners = SignerEntries::deserialize(*sleAccountSigners, ctx.j, "ledger"); @@ -816,7 +826,9 @@ Transactor::reset(XRPAmount fee) auto const balance = txnAcct->getFieldAmount(sfBalance).xrp(); // balance should have already been checked in checkFee / preFlight. - assert(balance != beast::zero && (!view().open() || balance >= fee)); + ASSERT( + balance != beast::zero && (!view().open() || balance >= fee), + "ripple::Transactor::reset : valid balance"); // We retry/reject the transaction if the account balance is zero or we're // applying against an open ledger and the balance is less than the fee @@ -831,7 +843,8 @@ Transactor::reset(XRPAmount fee) // reject the transaction. txnAcct->setFieldAmount(sfBalance, balance - fee); TER const ter{consumeSeqProxy(txnAcct)}; - assert(isTesSuccess(ter)); + ASSERT( + isTesSuccess(ter), "ripple::Transactor::reset : result is tesSUCCESS"); if (isTesSuccess(ter)) view().update(txnAcct); @@ -871,7 +884,8 @@ Transactor::operator()() JLOG(j_.fatal()) << "Transaction serdes mismatch"; JLOG(j_.info()) << to_string(ctx_.tx.getJson(JsonOptions::none)); JLOG(j_.fatal()) << s2.getJson(JsonOptions::none); - assert(false); + UNREACHABLE( + "ripple::Transactor::operator() : transaction serdes mismatch"); } } #endif @@ -888,7 +902,9 @@ Transactor::operator()() // No transaction can return temUNKNOWN from apply, // and it can't be passed in from a preclaim. - assert(result != temUNKNOWN); + ASSERT( + result != temUNKNOWN, + "ripple::Transactor::operator() : result is not temUNKNOWN"); if (auto stream = j_.trace()) stream << "preclaim result: " << transToken(result); @@ -944,7 +960,10 @@ Transactor::operator()() std::shared_ptr const& after) { if (isDelete) { - assert(before && after); + ASSERT( + before && after, + "ripple::Transactor::operator()::visit : non-null SLE " + "inputs"); if (doOffers && before && after && (before->getType() == ltOFFER) && (before->getFieldAmount(sfTakerPays) == diff --git a/src/xrpld/app/tx/detail/XChainBridge.cpp b/src/xrpld/app/tx/detail/XChainBridge.cpp index f5633903567..7485ff6c4b0 100644 --- a/src/xrpld/app/tx/detail/XChainBridge.cpp +++ b/src/xrpld/app/tx/detail/XChainBridge.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -222,7 +223,9 @@ claimHelper( auto i = signersList.find(a.keyAccount); if (i == signersList.end()) { - assert(0); // should have already been checked + UNREACHABLE( + "ripple::claimHelper : invalid inputs"); // should have already + // been checked continue; } weight += i->second; @@ -437,7 +440,9 @@ transferHelper( if (amt.native()) { auto const sleSrc = psb.peek(keylet::account(src)); - assert(sleSrc); + ASSERT( + sleSrc != nullptr, + "ripple::transferHelper : non-null source account"); if (!sleSrc) return tecINTERNAL; diff --git a/src/xrpld/app/tx/detail/applySteps.cpp b/src/xrpld/app/tx/detail/applySteps.cpp index b3c711084dc..24d6d6bb61f 100644 --- a/src/xrpld/app/tx/detail/applySteps.cpp +++ b/src/xrpld/app/tx/detail/applySteps.cpp @@ -157,7 +157,7 @@ invoke_preflight(PreflightContext const& ctx) // Should never happen JLOG(ctx.j.fatal()) << "Unknown transaction type in preflight: " << e.txnType; - assert(false); + UNREACHABLE("ripple::invoke_preflight : unknown transaction type"); return {temUNKNOWN, TxConsequences{temUNKNOWN}}; } } @@ -206,7 +206,7 @@ invoke_preclaim(PreclaimContext const& ctx) // Should never happen JLOG(ctx.j.fatal()) << "Unknown transaction type in preclaim: " << e.txnType; - assert(false); + UNREACHABLE("ripple::invoke_preclaim : unknown transaction type"); return temUNKNOWN; } } @@ -222,7 +222,8 @@ invoke_calculateBaseFee(ReadView const& view, STTx const& tx) } catch (UnknownTxnType const& e) { - assert(false); + UNREACHABLE( + "ripple::invoke_calculateBaseFee : unknown transaction type"); return XRPAmount{0}; } } @@ -234,7 +235,9 @@ TxConsequences::TxConsequences(NotTEC pfresult) , seqProx_(SeqProxy::sequence(0)) , sequencesConsumed_(0) { - assert(!isTesSuccess(pfresult)); + ASSERT( + !isTesSuccess(pfresult), + "ripple::TxConsequences::TxConsequences : is not tesSUCCESS"); } TxConsequences::TxConsequences(STTx const& tx) @@ -281,7 +284,7 @@ invoke_apply(ApplyContext& ctx) // Should never happen JLOG(ctx.journal.fatal()) << "Unknown transaction type in apply: " << e.txnType; - assert(false); + UNREACHABLE("ripple::invoke_apply : unknown transaction type"); return {temUNKNOWN, false}; } } diff --git a/src/xrpld/consensus/Consensus.h b/src/xrpld/consensus/Consensus.h index 06c12b4f150..7b8d03f48a7 100644 --- a/src/xrpld/consensus/Consensus.h +++ b/src/xrpld/consensus/Consensus.h @@ -863,7 +863,9 @@ Consensus::gotTxSet( { // Our position is added to acquired_ as soon as we create it, // so this txSet must differ - assert(id != result_->position.position()); + ASSERT( + id != result_->position.position(), + "ripple::Consensus::gotTxSet : updated transaction set"); bool any = false; for (auto const& [nodeId, peerPos] : currPeerPositions_) { @@ -1008,7 +1010,9 @@ template void Consensus::handleWrongLedger(typename Ledger_t::ID const& lgrId) { - assert(lgrId != prevLedgerID_ || previousLedger_.id() != lgrId); + ASSERT( + lgrId != prevLedgerID_ || previousLedger_.id() != lgrId, + "ripple::Consensus::handleWrongLedger : have wrong ledger"); // Stop proposing because we are out of sync leaveConsensus(); @@ -1259,7 +1263,9 @@ void Consensus::phaseEstablish() { // can only establish consensus if we already took a stance - assert(result_); + ASSERT( + result_.has_value(), + "ripple::Consensus::phaseEstablish : result is set"); using namespace std::chrono; ConsensusParms const& parms = adaptor_.parms(); @@ -1307,7 +1313,7 @@ void Consensus::closeLedger() { // We should not be closing if we already have a position - assert(!result_); + ASSERT(!result_, "ripple::Consensus::closeLedger : result is not set"); phase_ = ConsensusPhase::establish; JLOG(j_.debug()) << "transitioned to ConsensusPhase::establish"; @@ -1360,7 +1366,9 @@ void Consensus::updateOurPositions() { // We must have a position if we are updating it - assert(result_); + ASSERT( + result_.has_value(), + "ripple::Consensus::updateOurPositions : result is set"); ConsensusParms const& parms = adaptor_.parms(); // Compute a cutoff time @@ -1544,7 +1552,8 @@ bool Consensus::haveConsensus() { // Must have a stance if we are checking for consensus - assert(result_); + ASSERT( + result_.has_value(), "ripple::Consensus::haveConsensus : has result"); // CHECKME: should possibly count unacquired TX sets as disagreeing int agree = 0, disagree = 0; @@ -1619,7 +1628,9 @@ void Consensus::createDisputes(TxSet_t const& o) { // Cannot create disputes without our stance - assert(result_); + ASSERT( + result_.has_value(), + "ripple::Consensus::createDisputes : result is set"); // Only create disputes if this is a new set if (!result_->compares.emplace(o.id()).second) @@ -1640,9 +1651,10 @@ Consensus::createDisputes(TxSet_t const& o) { ++dc; // create disputed transactions (from the ledger that has them) - assert( + ASSERT( (inThisSet && result_->txns.find(txId) && !o.find(txId)) || - (!inThisSet && !result_->txns.find(txId) && o.find(txId))); + (!inThisSet && !result_->txns.find(txId) && o.find(txId)), + "ripple::Consensus::createDisputes : has disputed transactions"); Tx_t tx = inThisSet ? result_->txns.find(txId) : o.find(txId); auto txID = tx.id(); @@ -1678,7 +1690,9 @@ void Consensus::updateDisputes(NodeID_t const& node, TxSet_t const& other) { // Cannot updateDisputes without our stance - assert(result_); + ASSERT( + result_.has_value(), + "ripple::Consensus::updateDisputes : result is set"); // Ensure we have created disputes against this set if we haven't seen // it before diff --git a/src/xrpld/consensus/ConsensusTypes.h b/src/xrpld/consensus/ConsensusTypes.h index da03fc4875a..15bc858848d 100644 --- a/src/xrpld/consensus/ConsensusTypes.h +++ b/src/xrpld/consensus/ConsensusTypes.h @@ -214,7 +214,9 @@ struct ConsensusResult ConsensusResult(TxSet_t&& s, Proposal_t&& p) : txns{std::move(s)}, position{std::move(p)} { - assert(txns.id() == position.position()); + ASSERT( + txns.id() == position.position(), + "ripple::ConsensusResult : valid inputs"); } //! The set of transactions consensus agrees go in the ledger diff --git a/src/xrpld/consensus/LedgerTiming.h b/src/xrpld/consensus/LedgerTiming.h index 1bb5bfd730f..57247abe968 100644 --- a/src/xrpld/consensus/LedgerTiming.h +++ b/src/xrpld/consensus/LedgerTiming.h @@ -82,7 +82,9 @@ getNextLedgerTimeResolution( bool previousAgree, Seq ledgerSeq) { - assert(ledgerSeq != Seq{0}); + ASSERT( + ledgerSeq != Seq{0}, + "ripple:getNextLedgerTimeResolution : valid ledger sequence"); using namespace std::chrono; // Find the current resolution: @@ -90,7 +92,9 @@ getNextLedgerTimeResolution( std::begin(ledgerPossibleTimeResolutions), std::end(ledgerPossibleTimeResolutions), previousResolution); - assert(iter != std::end(ledgerPossibleTimeResolutions)); + ASSERT( + iter != std::end(ledgerPossibleTimeResolutions), + "ripple:getNextLedgerTimeResolution : found time resolution"); // This should never happen, but just as a precaution if (iter == std::end(ledgerPossibleTimeResolutions)) diff --git a/src/xrpld/consensus/LedgerTrie.h b/src/xrpld/consensus/LedgerTrie.h index 32bae28cc07..ad1797d51fe 100644 --- a/src/xrpld/consensus/LedgerTrie.h +++ b/src/xrpld/consensus/LedgerTrie.h @@ -21,7 +21,9 @@ #define RIPPLE_APP_CONSENSUS_LEDGERS_TRIE_H_INCLUDED #include +#include #include + #include #include #include @@ -62,7 +64,7 @@ class SpanTip ID ancestor(Seq const& s) const { - assert(s <= seq); + ASSERT(s <= seq, "ripple::SpanTip::ancestor : valid input"); return ledger[s]; } @@ -88,7 +90,8 @@ class Span Span() : ledger_{typename Ledger::MakeGenesis{}} { // Require default ledger to be genesis seq - assert(ledger_.seq() == start_); + ASSERT( + ledger_.seq() == start_, "ripple::Span::Span : ledger is genesis"); } Span(Ledger ledger) @@ -157,7 +160,7 @@ class Span : start_{start}, end_{end}, ledger_{l} { // Spans cannot be empty - assert(start < end); + ASSERT(start < end, "ripple::Span::Span : non-empty span input"); } Seq @@ -230,7 +233,7 @@ struct Node [child](std::unique_ptr const& curr) { return curr.get() == child; }); - assert(it != children.end()); + ASSERT(it != children.end(), "ripple::Node::erase : valid input"); std::swap(*it, children.back()); children.pop_back(); } @@ -371,7 +374,7 @@ class LedgerTrie Node* curr = root.get(); // Root is always defined and is in common with all ledgers - assert(curr); + ASSERT(curr != nullptr, "ripple::LedgerTrie::find : non-null root"); Seq pos = curr->span.diff(ledger); bool done = false; @@ -452,7 +455,8 @@ class LedgerTrie auto const [loc, diffSeq] = find(ledger); // There is always a place to insert - assert(loc); + ASSERT( + loc != nullptr, "ripple::LedgerTrie::insert : valid input ledger"); // Node from which to start incrementing branchSupport Node* incNode = loc; @@ -487,12 +491,16 @@ class LedgerTrie newNode->tipSupport = loc->tipSupport; newNode->branchSupport = loc->branchSupport; newNode->children = std::move(loc->children); - assert(loc->children.empty()); + ASSERT( + loc->children.empty(), + "ripple::LedgerTrie::insert : moved-from children"); for (std::unique_ptr& child : newNode->children) child->parent = newNode.get(); // Loc truncates to prefix and newNode is its child - assert(prefix); + ASSERT( + prefix.has_value(), + "ripple::LedgerTrie::insert : prefix is set"); loc->span = *prefix; newNode->parent = loc; loc->children.emplace_back(std::move(newNode)); @@ -545,7 +553,9 @@ class LedgerTrie loc->tipSupport -= count; auto const it = seqSupport.find(ledger.seq()); - assert(it != seqSupport.end() && it->second >= count); + ASSERT( + it != seqSupport.end() && it->second >= count, + "ripple::LedgerTrie::remove : valid input ledger"); it->second -= count; if (it->second == 0) seqSupport.erase(it->first); diff --git a/src/xrpld/consensus/Validations.h b/src/xrpld/consensus/Validations.h index a1171effb56..765298d897a 100644 --- a/src/xrpld/consensus/Validations.h +++ b/src/xrpld/consensus/Validations.h @@ -434,7 +434,9 @@ class Validations Validation const& val, std::optional> prior) { - assert(val.trusted()); + ASSERT( + val.trusted(), + "ripple::Validations::updateTrie : trusted input validation"); // Clear any prior acquiring ledger for this node if (prior) @@ -713,7 +715,7 @@ class Validations setSeqToKeep(Seq const& low, Seq const& high) { std::lock_guard lock{mutex_}; - assert(low < high); + ASSERT(low < high, "ripple::Validations::setSeqToKeep : valid inputs"); toKeep_ = {low, high}; } diff --git a/src/xrpld/core/Coro.ipp b/src/xrpld/core/Coro.ipp index a936dd896ae..a046971015e 100644 --- a/src/xrpld/core/Coro.ipp +++ b/src/xrpld/core/Coro.ipp @@ -53,7 +53,7 @@ JobQueue::Coro::Coro( inline JobQueue::Coro::~Coro() { #ifndef NDEBUG - assert(finished_); + ASSERT(finished_, "ripple::JobQueue::Coro::~Coro : is finished"); #endif } @@ -103,7 +103,9 @@ JobQueue::Coro::resume() auto saved = detail::getLocalValues().release(); detail::getLocalValues().reset(&lvs_); std::lock_guard lock(mutex_); - assert(coro_); + ASSERT( + static_cast(coro_), + "ripple::JobQueue::Coro::resume : is runnable"); coro_(); detail::getLocalValues().release(); detail::getLocalValues().reset(saved); diff --git a/src/xrpld/core/DatabaseCon.h b/src/xrpld/core/DatabaseCon.h index c8c40dec662..bb6f36d4d56 100644 --- a/src/xrpld/core/DatabaseCon.h +++ b/src/xrpld/core/DatabaseCon.h @@ -97,7 +97,10 @@ class DatabaseCon std::vector const* commonPragma() const { - assert(!useGlobalPragma || globalPragma); + ASSERT( + !useGlobalPragma || globalPragma, + "ripple::DatabaseCon::Setup::commonPragma : consistent global " + "pragma"); return useGlobalPragma && globalPragma ? globalPragma.get() : nullptr; } diff --git a/src/xrpld/core/JobTypes.h b/src/xrpld/core/JobTypes.h index 3b41ce7ff47..5963446cd43 100644 --- a/src/xrpld/core/JobTypes.h +++ b/src/xrpld/core/JobTypes.h @@ -53,17 +53,22 @@ class JobTypes int limit, std::chrono::milliseconds avgLatency, std::chrono::milliseconds peakLatency) { - assert(m_map.find(jt) == m_map.end()); - - auto const [_, inserted] = m_map.emplace( - std::piecewise_construct, - std::forward_as_tuple(jt), - std::forward_as_tuple( - jt, name, limit, avgLatency, peakLatency)); - - assert(inserted == true); - (void)_; - (void)inserted; + ASSERT( + m_map.find(jt) == m_map.end(), + "ripple::JobTypes::JobTypes::add : unique job type input"); + + [[maybe_unused]] auto const inserted = + m_map + .emplace( + std::piecewise_construct, + std::forward_as_tuple(jt), + std::forward_as_tuple( + jt, name, limit, avgLatency, peakLatency)) + .second; + + ASSERT( + inserted == true, + "ripple::JobTypes::JobTypes::add : input is inserted"); }; // clang-format off @@ -137,7 +142,7 @@ class JobTypes get(JobType jt) const { Map::const_iterator const iter(m_map.find(jt)); - assert(iter != m_map.end()); + ASSERT(iter != m_map.end(), "ripple::JobTypes::get : valid input"); if (iter != m_map.end()) return iter->second; diff --git a/src/xrpld/core/detail/Config.cpp b/src/xrpld/core/detail/Config.cpp index 885951111c0..b37a931bca0 100644 --- a/src/xrpld/core/detail/Config.cpp +++ b/src/xrpld/core/detail/Config.cpp @@ -266,7 +266,7 @@ Config::Config() void Config::setupControl(bool bQuiet, bool bSilent, bool bStandalone) { - assert(NODE_SIZE == 0); + ASSERT(NODE_SIZE == 0, "ripple::Config::setupControl : node size not set"); QUIET = bQuiet || bSilent; SILENT = bSilent; @@ -287,7 +287,9 @@ Config::setupControl(bool bQuiet, bool bSilent, bool bStandalone) return (limit == 0) || (ramSize_ < limit); }); - assert(ns != threshold.second.end()); + ASSERT( + ns != threshold.second.end(), + "ripple::Config::setupControl : valid node size"); if (ns != threshold.second.end()) NODE_SIZE = std::distance(threshold.second.begin(), ns); @@ -298,7 +300,7 @@ Config::setupControl(bool bQuiet, bool bSilent, bool bStandalone) NODE_SIZE = std::min(hc / 2, NODE_SIZE); } - assert(NODE_SIZE <= 4); + ASSERT(NODE_SIZE <= 4, "ripple::Config::setupControl : node size is set"); } void @@ -1004,8 +1006,12 @@ int Config::getValueFor(SizedItem item, std::optional node) const { auto const index = static_cast>(item); - assert(index < sizedItems.size()); - assert(!node || *node <= 4); + ASSERT( + index < sizedItems.size(), + "ripple::Config::getValueFor : valid index input"); + ASSERT( + !node || *node <= 4, + "ripple::Config::getValueFor : unset or valid node"); return sizedItems.at(index).second.at(node.value_or(NODE_SIZE)); } diff --git a/src/xrpld/core/detail/DatabaseCon.cpp b/src/xrpld/core/detail/DatabaseCon.cpp index 7000899b1f6..d93a66cfb83 100644 --- a/src/xrpld/core/detail/DatabaseCon.cpp +++ b/src/xrpld/core/detail/DatabaseCon.cpp @@ -231,7 +231,9 @@ setup_DatabaseCon(Config const& c, std::optional j) "nodes storing large amounts of history, because of the " "difficulty inherent in rebuilding corrupted data."; } - assert(result->size() == 3); + ASSERT( + result->size() == 3, + "ripple::setup_DatabaseCon::globalPragma : result size is 3"); return result; }(); } diff --git a/src/xrpld/core/detail/Job.cpp b/src/xrpld/core/detail/Job.cpp index 0782fd05a66..17f600a4f41 100644 --- a/src/xrpld/core/detail/Job.cpp +++ b/src/xrpld/core/detail/Job.cpp @@ -19,7 +19,7 @@ #include #include -#include +#include namespace ripple { diff --git a/src/xrpld/core/detail/JobQueue.cpp b/src/xrpld/core/detail/JobQueue.cpp index 1c859d724f4..3e87dd22212 100644 --- a/src/xrpld/core/detail/JobQueue.cpp +++ b/src/xrpld/core/detail/JobQueue.cpp @@ -55,7 +55,9 @@ JobQueue::JobQueue( std::piecewise_construct, std::forward_as_tuple(jt.type()), std::forward_as_tuple(jt, m_collector, logs))); - assert(result.second == true); + ASSERT( + result.second == true, + "ripple::JobQueue::JobQueue : jobs added"); (void)result.second; } } @@ -80,10 +82,14 @@ JobQueue::addRefCountedJob( std::string const& name, JobFunction const& func) { - assert(type != jtINVALID); + ASSERT( + type != jtINVALID, + "ripple::JobQueue::addRefCountedJob : valid input job type"); auto iter(m_jobData.find(type)); - assert(iter != m_jobData.end()); + ASSERT( + iter != m_jobData.end(), + "ripple::JobQueue::addRefCountedJob : job type found in jobs"); if (iter == m_jobData.end()) return false; @@ -93,9 +99,11 @@ JobQueue::addRefCountedJob( // FIXME: Workaround incorrect client shutdown ordering // do not add jobs to a queue with no threads - assert( + ASSERT( (type >= jtCLIENT && type <= jtCLIENT_WEBSOCKET) || - m_workers.getNumberOfThreads() > 0); + m_workers.getNumberOfThreads() > 0, + "ripple::JobQueue::addRefCountedJob : threads available or job " + "requires no threads"); { std::lock_guard lock(m_mutex); @@ -104,8 +112,12 @@ JobQueue::addRefCountedJob( auto const& job = *result.first; JobType const type(job.getType()); - assert(type != jtINVALID); - assert(m_jobSet.find(job) != m_jobSet.end()); + ASSERT( + type != jtINVALID, + "ripple::JobQueue::addRefCountedJob : has valid job type"); + ASSERT( + m_jobSet.find(job) != m_jobSet.end(), + "ripple::JobQueue::addRefCountedJob : job found"); perfLog_.jobQueue(type); JobTypeData& data(getJobTypeData(type)); @@ -165,7 +177,9 @@ std::unique_ptr JobQueue::makeLoadEvent(JobType t, std::string const& name) { JobDataMap::iterator iter(m_jobData.find(t)); - assert(iter != m_jobData.end()); + ASSERT( + iter != m_jobData.end(), + "ripple::JobQueue::makeLoadEvent : valid job type input"); if (iter == m_jobData.end()) return {}; @@ -180,7 +194,9 @@ JobQueue::addLoadEvents(JobType t, int count, std::chrono::milliseconds elapsed) LogicError("JobQueue::addLoadEvents() called after JobQueue stopped"); JobDataMap::iterator iter(m_jobData.find(t)); - assert(iter != m_jobData.end()); + ASSERT( + iter != m_jobData.end(), + "ripple::JobQueue::addLoadEvents : valid job type input"); iter->second.load().addSamples(count, elapsed); } @@ -206,7 +222,8 @@ JobQueue::getJson(int c) for (auto& x : m_jobData) { - assert(x.first != jtINVALID); + ASSERT( + x.first != jtINVALID, "ripple::JobQueue::getJson : valid job type"); if (x.first == jtGENERIC) continue; @@ -261,7 +278,9 @@ JobTypeData& JobQueue::getJobTypeData(JobType type) { JobDataMap::iterator c(m_jobData.find(type)); - assert(c != m_jobData.end()); + ASSERT( + c != m_jobData.end(), + "ripple::JobQueue::getJobTypeData : valid job type input"); // NIKB: This is ugly and I hate it. We must remove jtINVALID completely // and use something sane. @@ -286,9 +305,11 @@ JobQueue::stop() std::unique_lock lock(m_mutex); cv_.wait( lock, [this] { return m_processCount == 0 && m_jobSet.empty(); }); - assert(m_processCount == 0); - assert(m_jobSet.empty()); - assert(nSuspend_ == 0); + ASSERT( + m_processCount == 0, + "ripple::JobQueue::stop : all processes completed"); + ASSERT(m_jobSet.empty(), "ripple::JobQueue::stop : all jobs completed"); + ASSERT(nSuspend_ == 0, "ripple::JobQueue::stop : no coros suspended"); stopped_ = true; } } @@ -302,28 +323,35 @@ JobQueue::isStopped() const void JobQueue::getNextJob(Job& job) { - assert(!m_jobSet.empty()); + ASSERT(!m_jobSet.empty(), "ripple::JobQueue::getNextJob : non-empty jobs"); std::set::const_iterator iter; for (iter = m_jobSet.begin(); iter != m_jobSet.end(); ++iter) { JobType const type = iter->getType(); - assert(type != jtINVALID); + ASSERT( + type != jtINVALID, "ripple::JobQueue::getNextJob : valid job type"); JobTypeData& data(getJobTypeData(type)); - assert(data.running <= getJobLimit(type)); + ASSERT( + data.running <= getJobLimit(type), + "ripple::JobQueue::getNextJob : maximum jobs running"); // Run this job if we're running below the limit. if (data.running < getJobLimit(data.type())) { - assert(data.waiting > 0); + ASSERT( + data.waiting > 0, + "ripple::JobQueue::getNextJob : positive data waiting"); --data.waiting; ++data.running; break; } } - assert(iter != m_jobSet.end()); + ASSERT( + iter != m_jobSet.end(), + "ripple::JobQueue::getNextJob : found next job"); job = *iter; m_jobSet.erase(iter); } @@ -331,14 +359,18 @@ JobQueue::getNextJob(Job& job) void JobQueue::finishJob(JobType type) { - assert(type != jtINVALID); + ASSERT( + type != jtINVALID, + "ripple::JobQueue::finishJob : valid input job type"); JobTypeData& data = getJobTypeData(type); // Queue a deferred task if possible if (data.deferred > 0) { - assert(data.running + data.waiting >= getJobLimit(type)); + ASSERT( + data.running + data.waiting >= getJobLimit(type), + "ripple::JobQueue::finishJob : job limit"); --data.deferred; m_workers.addTask(); @@ -404,7 +436,9 @@ int JobQueue::getJobLimit(JobType type) { JobTypeInfo const& j(JobTypes::instance().get(type)); - assert(j.type() != jtINVALID); + ASSERT( + j.type() != jtINVALID, + "ripple::JobQueue::getJobLimit : valid job type"); return j.limit(); } diff --git a/src/xrpld/core/detail/LoadEvent.cpp b/src/xrpld/core/detail/LoadEvent.cpp index ca78fdb19cc..b9c1de79a33 100644 --- a/src/xrpld/core/detail/LoadEvent.cpp +++ b/src/xrpld/core/detail/LoadEvent.cpp @@ -19,7 +19,7 @@ #include #include -#include +#include #include namespace ripple { @@ -83,7 +83,7 @@ LoadEvent::start() void LoadEvent::stop() { - assert(running_); + ASSERT(running_, "ripple::LoadEvent::stop : is running"); auto const now = std::chrono::steady_clock::now(); diff --git a/src/xrpld/core/detail/Workers.cpp b/src/xrpld/core/detail/Workers.cpp index ff861010d95..32e6ace4402 100644 --- a/src/xrpld/core/detail/Workers.cpp +++ b/src/xrpld/core/detail/Workers.cpp @@ -20,7 +20,7 @@ #include #include #include -#include +#include namespace ripple { @@ -119,7 +119,9 @@ Workers::stop() m_cv.wait(lk, [this] { return m_allPaused; }); lk.unlock(); - assert(numberOfCurrentlyRunningTasks() == 0); + ASSERT( + numberOfCurrentlyRunningTasks() == 0, + "ripple::Workers::stop : zero running tasks"); } void diff --git a/src/xrpld/ledger/ApplyView.h b/src/xrpld/ledger/ApplyView.h index f0166cd0b38..12626824308 100644 --- a/src/xrpld/ledger/ApplyView.h +++ b/src/xrpld/ledger/ApplyView.h @@ -23,6 +23,7 @@ #include #include #include +#include namespace ripple { @@ -276,8 +277,11 @@ class ApplyView : public ReadView { if (key.type != ltOFFER) { - assert(!"Only Offers are appended to book directories. " - "Call dirInsert() instead."); + UNREACHABLE( + "ripple::ApplyView::dirAppend : only Offers are appended to " + "book directories"); + // Only Offers are appended to book directories. Call dirInsert() + // instead return std::nullopt; } return dirAdd(true, directory, key.key, describe); diff --git a/src/xrpld/ledger/ReadView.h b/src/xrpld/ledger/ReadView.h index 50f1a7d98c1..efe920805ad 100644 --- a/src/xrpld/ledger/ReadView.h +++ b/src/xrpld/ledger/ReadView.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -35,7 +36,6 @@ #include #include #include -#include #include #include #include diff --git a/src/xrpld/ledger/detail/ApplyStateTable.cpp b/src/xrpld/ledger/detail/ApplyStateTable.cpp index b849365c83f..2649ac2e207 100644 --- a/src/xrpld/ledger/detail/ApplyStateTable.cpp +++ b/src/xrpld/ledger/detail/ApplyStateTable.cpp @@ -19,10 +19,10 @@ #include #include +#include #include #include #include -#include namespace ripple { namespace detail { @@ -155,7 +155,10 @@ ApplyStateTable::apply( meta.setAffectedNode(item.first, *type, nodeType); if (type == &sfDeletedNode) { - assert(origNode && curNode); + ASSERT( + origNode && curNode, + "ripple::detail::ApplyStateTable::apply : valid nodes for " + "deletion"); threadOwners(to, meta, origNode, newMod, j); STObject prevs(sfPreviousFields); @@ -187,7 +190,10 @@ ApplyStateTable::apply( } else if (type == &sfModifiedNode) { - assert(curNode && origNode); + ASSERT( + curNode && origNode, + "ripple::detail::ApplyStateTable::apply : valid nodes for " + "modification"); if (curNode->isThreadedType( to.rules())) // thread transaction to node @@ -222,7 +228,10 @@ ApplyStateTable::apply( } else if (type == &sfCreatedNode) // if created, thread to owner(s) { - assert(curNode && !origNode); + ASSERT( + curNode && !origNode, + "ripple::detail::ApplyStateTable::apply : valid nodes for " + "creation"); threadOwners(to, meta, curNode, newMod, j); if (curNode->isThreadedType( @@ -245,7 +254,9 @@ ApplyStateTable::apply( } else { - assert(false); + UNREACHABLE( + "ripple::detail::ApplyStateTable::apply : unsupported " + "operation type"); } } @@ -536,13 +547,21 @@ ApplyStateTable::threadItem(TxMeta& meta, std::shared_ptr const& sle) if (node.getFieldIndex(sfPreviousTxnID) == -1) { - assert(node.getFieldIndex(sfPreviousTxnLgrSeq) == -1); + ASSERT( + node.getFieldIndex(sfPreviousTxnLgrSeq) == -1, + "ripple::ApplyStateTable::threadItem : previous ledger is not " + "set"); node.setFieldH256(sfPreviousTxnID, prevTxID); node.setFieldU32(sfPreviousTxnLgrSeq, prevLgrID); } - assert(node.getFieldH256(sfPreviousTxnID) == prevTxID); - assert(node.getFieldU32(sfPreviousTxnLgrSeq) == prevLgrID); + ASSERT( + node.getFieldH256(sfPreviousTxnID) == prevTxID, + "ripple::ApplyStateTable::threadItem : previous transaction is a " + "match"); + ASSERT( + node.getFieldU32(sfPreviousTxnLgrSeq) == prevLgrID, + "ripple::ApplyStateTable::threadItem : previous ledger is a match"); } } @@ -557,7 +576,9 @@ ApplyStateTable::getForMod( auto miter = mods.find(key); if (miter != mods.end()) { - assert(miter->second); + ASSERT( + miter->second != nullptr, + "ripple::ApplyStateTable::getForMod : non-null result"); return miter->second; } } @@ -613,7 +634,9 @@ ApplyStateTable::threadTx( return; } // threadItem only applied to AccountRoot - assert(sle->isThreadedType(base.rules())); + ASSERT( + sle->isThreadedType(base.rules()), + "ripple::ApplyStateTable::threadTx : SLE is threaded"); threadItem(meta, sle); } diff --git a/src/xrpld/ledger/detail/ApplyView.cpp b/src/xrpld/ledger/detail/ApplyView.cpp index 735aa9906e0..8b491bdcb2b 100644 --- a/src/xrpld/ledger/detail/ApplyView.cpp +++ b/src/xrpld/ledger/detail/ApplyView.cpp @@ -19,8 +19,8 @@ #include #include +#include #include -#include namespace ripple { @@ -133,7 +133,7 @@ ApplyView::emptyDirDelete(Keylet const& directory) if (directory.type != ltDIR_NODE || node->getFieldH256(sfRootIndex) != directory.key) { - assert(!"emptyDirDelete() called with wrong node type"); + UNREACHABLE("ripple::ApplyView::emptyDirDelete : invalid node type"); return false; } diff --git a/src/xrpld/ledger/detail/ApplyViewImpl.cpp b/src/xrpld/ledger/detail/ApplyViewImpl.cpp index ffbf681cd20..e01b8bfe3ba 100644 --- a/src/xrpld/ledger/detail/ApplyViewImpl.cpp +++ b/src/xrpld/ledger/detail/ApplyViewImpl.cpp @@ -19,7 +19,7 @@ #include #include -#include +#include namespace ripple { diff --git a/src/xrpld/ledger/detail/BookDirs.cpp b/src/xrpld/ledger/detail/BookDirs.cpp index 58527b02ff2..4561aa2df18 100644 --- a/src/xrpld/ledger/detail/BookDirs.cpp +++ b/src/xrpld/ledger/detail/BookDirs.cpp @@ -30,12 +30,12 @@ BookDirs::BookDirs(ReadView const& view, Book const& book) , next_quality_(getQualityNext(root_)) , key_(view_->succ(root_, next_quality_).value_or(beast::zero)) { - assert(root_ != beast::zero); + ASSERT(root_ != beast::zero, "ripple::BookDirs::BookDirs : nonzero root"); if (key_ != beast::zero) { if (!cdirFirst(*view_, key_, sle_, entry_, index_)) { - assert(false); + UNREACHABLE("ripple::BookDirs::BookDirs : directory is empty"); } } } @@ -70,7 +70,10 @@ BookDirs::const_iterator::operator==( if (view_ == nullptr || other.view_ == nullptr) return false; - assert(view_ == other.view_ && root_ == other.root_); + ASSERT( + view_ == other.view_ && root_ == other.root_, + "ripple::BookDirs::const_iterator::operator== : views and roots are " + "matching"); return entry_ == other.entry_ && cur_key_ == other.cur_key_ && index_ == other.index_; } @@ -78,7 +81,9 @@ BookDirs::const_iterator::operator==( BookDirs::const_iterator::reference BookDirs::const_iterator::operator*() const { - assert(index_ != beast::zero); + ASSERT( + index_ != beast::zero, + "ripple::BookDirs::const_iterator::operator* : nonzero index"); if (!cache_) cache_ = view_->read(keylet::offer(index_)); return *cache_; @@ -89,7 +94,9 @@ BookDirs::const_iterator::operator++() { using beast::zero; - assert(index_ != zero); + ASSERT( + index_ != zero, + "ripple::BookDirs::const_iterator::operator++ : nonzero index"); if (!cdirNext(*view_, cur_key_, sle_, entry_, index_)) { if (index_ != 0 || @@ -102,7 +109,9 @@ BookDirs::const_iterator::operator++() } else if (!cdirFirst(*view_, cur_key_, sle_, entry_, index_)) { - assert(false); + UNREACHABLE( + "ripple::BookDirs::const_iterator::operator++ : directory is " + "empty"); } } @@ -113,7 +122,9 @@ BookDirs::const_iterator::operator++() BookDirs::const_iterator BookDirs::const_iterator::operator++(int) { - assert(index_ != beast::zero); + ASSERT( + index_ != beast::zero, + "ripple::BookDirs::const_iterator::operator++(int) : nonzero index"); const_iterator tmp(*this); ++(*this); return tmp; diff --git a/src/xrpld/ledger/detail/Dir.cpp b/src/xrpld/ledger/detail/Dir.cpp index 6004a73095c..24c88a52f09 100644 --- a/src/xrpld/ledger/detail/Dir.cpp +++ b/src/xrpld/ledger/detail/Dir.cpp @@ -60,14 +60,18 @@ const_iterator::operator==(const_iterator const& other) const if (view_ == nullptr || other.view_ == nullptr) return false; - assert(view_ == other.view_ && root_.key == other.root_.key); + ASSERT( + view_ == other.view_ && root_.key == other.root_.key, + "ripple::const_iterator::operator== : views and roots are matching"); return page_.key == other.page_.key && index_ == other.index_; } const_iterator::reference const_iterator::operator*() const { - assert(index_ != beast::zero); + ASSERT( + index_ != beast::zero, + "ripple::const_iterator::operator* : nonzero index"); if (!cache_) cache_ = view_->read(keylet::child(index_)); return *cache_; @@ -76,7 +80,9 @@ const_iterator::operator*() const const_iterator& const_iterator::operator++() { - assert(index_ != beast::zero); + ASSERT( + index_ != beast::zero, + "ripple::const_iterator::operator++ : nonzero index"); if (++it_ != std::end(*indexes_)) { index_ = *it_; @@ -90,7 +96,9 @@ const_iterator::operator++() const_iterator const_iterator::operator++(int) { - assert(index_ != beast::zero); + ASSERT( + index_ != beast::zero, + "ripple::const_iterator::operator++(int) : nonzero index"); const_iterator tmp(*this); ++(*this); return tmp; @@ -109,7 +117,9 @@ const_iterator::next_page() { page_ = keylet::page(root_, next); sle_ = view_->read(page_); - assert(sle_); + ASSERT( + sle_ != nullptr, + "ripple::const_iterator::next_page : non-null SLE"); indexes_ = &sle_->getFieldV256(sfIndexes); if (indexes_->empty()) { diff --git a/src/xrpld/ledger/detail/PaymentSandbox.cpp b/src/xrpld/ledger/detail/PaymentSandbox.cpp index d182d22b56c..3400427448d 100644 --- a/src/xrpld/ledger/detail/PaymentSandbox.cpp +++ b/src/xrpld/ledger/detail/PaymentSandbox.cpp @@ -20,12 +20,11 @@ #include #include #include +#include #include #include #include -#include - namespace ripple { namespace detail { @@ -49,8 +48,12 @@ DeferredCredits::credit( STAmount const& amount, STAmount const& preCreditSenderBalance) { - assert(sender != receiver); - assert(!amount.negative()); + ASSERT( + sender != receiver, + "ripple::detail::DeferredCredits::credit : sender is not receiver"); + ASSERT( + !amount.negative(), + "ripple::detail::DeferredCredits::credit : positive amount"); auto const k = makeKey(sender, receiver, amount.getCurrency()); auto i = credits_.find(k); @@ -253,14 +256,14 @@ PaymentSandbox::adjustOwnerCountHook( void PaymentSandbox::apply(RawView& to) { - assert(!ps_); + ASSERT(!ps_, "ripple::PaymentSandbox::apply : non-null sandbox"); items_.apply(to); } void PaymentSandbox::apply(PaymentSandbox& to) { - assert(ps_ == &to); + ASSERT(ps_ == &to, "ripple::PaymentSandbox::apply : matching sandbox"); items_.apply(to); tab_.apply(to.tab_); } @@ -344,7 +347,10 @@ PaymentSandbox::balanceChanges(ReadView const& view) const { // modify auto const at = after->getType(); - assert(at == before->getType()); + ASSERT( + at == before->getType(), + "ripple::PaymentSandbox::balanceChanges : after and before " + "types matching"); switch (at) { case ltACCOUNT_ROOT: diff --git a/src/xrpld/ledger/detail/RawStateTable.cpp b/src/xrpld/ledger/detail/RawStateTable.cpp index 4d3732f8a45..f8c575fc520 100644 --- a/src/xrpld/ledger/detail/RawStateTable.cpp +++ b/src/xrpld/ledger/detail/RawStateTable.cpp @@ -63,7 +63,10 @@ class RawStateTable::sles_iter_impl : public ReadView::sles_type::iter_base { if (auto const p = dynamic_cast(&impl)) { - assert(end1_ == p->end1_ && end0_ == p->end0_); + ASSERT( + end1_ == p->end1_ && end0_ == p->end0_, + "ripple::detail::RawStateTable::equal : matching end " + "iterators"); return iter1_ == p->iter1_ && iter0_ == p->iter0_; } @@ -73,7 +76,10 @@ class RawStateTable::sles_iter_impl : public ReadView::sles_type::iter_base void increment() override { - assert(sle1_ || sle0_); + ASSERT( + sle1_ || sle0_, + "ripple::detail::RawStateTable::increment : either SLE is " + "non-null"); if (sle1_ && !sle0_) { @@ -179,7 +185,9 @@ RawStateTable::apply(RawView& to) const bool RawStateTable::exists(ReadView const& base, Keylet const& k) const { - assert(k.key.isNonZero()); + ASSERT( + k.key.isNonZero(), + "ripple::detail::RawStateTable::exists : nonzero key"); auto const iter = items_.find(k.key); if (iter == items_.end()) return base.exists(k); diff --git a/src/xrpld/ledger/detail/ReadViewFwdRange.ipp b/src/xrpld/ledger/detail/ReadViewFwdRange.ipp index ae84259d7ce..844705a3f80 100644 --- a/src/xrpld/ledger/detail/ReadViewFwdRange.ipp +++ b/src/xrpld/ledger/detail/ReadViewFwdRange.ipp @@ -80,7 +80,10 @@ template bool ReadViewFwdRange::iterator::operator==(iterator const& other) const { - assert(view_ == other.view_); + ASSERT( + view_ == other.view_, + "ripple::detail::ReadViewFwdRange::iterator::operator==(iterator) " + "const : input view match"); if (impl_ != nullptr && other.impl_ != nullptr) return impl_->equal(*other.impl_); diff --git a/src/xrpld/ledger/detail/View.cpp b/src/xrpld/ledger/detail/View.cpp index ae4eb095017..23dbd81d5ad 100644 --- a/src/xrpld/ledger/detail/View.cpp +++ b/src/xrpld/ledger/detail/View.cpp @@ -22,11 +22,11 @@ #include #include #include +#include #include #include #include #include -#include #include namespace ripple { @@ -48,7 +48,9 @@ internalDirNext( uint256& entry) { auto const& svIndexes = page->getFieldV256(sfIndexes); - assert(index <= svIndexes.size()); + ASSERT( + index <= svIndexes.size(), + "ripple::detail::internalDirNext : index inside range"); if (index >= svIndexes.size()) { @@ -65,7 +67,8 @@ internalDirNext( else page = view.peek(keylet::page(root, next)); - assert(page); + ASSERT( + page != nullptr, "ripple::detail::internalDirNext : non-null root"); if (!page) return false; @@ -418,7 +421,7 @@ confineOwnerCount( << "Account " << *id << " owner count set below 0!"; } adjusted = 0; - assert(!id); + ASSERT(!id, "ripple::confineOwnerCount : id is not set"); } } return adjusted; @@ -467,7 +470,7 @@ forEachItem( Keylet const& root, std::function const&)> const& f) { - assert(root.type == ltDIR_NODE); + ASSERT(root.type == ltDIR_NODE, "ripple::forEachItem : valid root type"); if (root.type != ltDIR_NODE) return; @@ -497,7 +500,8 @@ forEachItemAfter( unsigned int limit, std::function const&)> const& f) { - assert(root.type == ltDIR_NODE); + ASSERT( + root.type == ltDIR_NODE, "ripple::forEachItemAfter : valid root type"); if (root.type != ltDIR_NODE) return false; @@ -772,9 +776,10 @@ hashOfSeq(ReadView const& ledger, LedgerIndex seq, beast::Journal journal) auto const hashIndex = ledger.read(keylet::skip()); if (hashIndex) { - assert( + ASSERT( hashIndex->getFieldU32(sfLastLedgerSequence) == - (ledger.seq() - 1)); + (ledger.seq() - 1), + "ripple::hashOfSeq : matching ledger sequence"); STVector256 vec = hashIndex->getFieldV256(sfHashes); if (vec.size() >= diff) return vec[vec.size() - diff]; @@ -802,8 +807,8 @@ hashOfSeq(ReadView const& ledger, LedgerIndex seq, beast::Journal journal) if (hashIndex) { auto const lastSeq = hashIndex->getFieldU32(sfLastLedgerSequence); - assert(lastSeq >= seq); - assert((lastSeq & 0xff) == 0); + ASSERT(lastSeq >= seq, "ripple::hashOfSeq : minimum last ledger"); + ASSERT((lastSeq & 0xff) == 0, "ripple::hashOfSeq : valid last ledger"); auto const diff = (lastSeq - seq) >> 8; STVector256 vec = hashIndex->getFieldV256(sfHashes); if (vec.size() > diff) @@ -829,7 +834,7 @@ adjustOwnerCount( { if (!sle) return; - assert(amount != 0); + ASSERT(amount != 0, "ripple::adjustOwnerCount : nonzero amount input"); std::uint32_t const current{sle->getFieldU32(sfOwnerCount)}; AccountID const id = (*sle)[sfAccount]; std::uint32_t const adjusted = confineOwnerCount(current, amount, id, j); @@ -894,13 +899,14 @@ trustCreate( const bool bSetDst = saLimit.getIssuer() == uDstAccountID; const bool bSetHigh = bSrcHigh ^ bSetDst; - assert(sleAccount); + ASSERT(sleAccount != nullptr, "ripple::trustCreate : non-null SLE"); if (!sleAccount) return tefINTERNAL; - assert( + ASSERT( sleAccount->getAccountID(sfAccount) == - (bSetHigh ? uHighAccountID : uLowAccountID)); + (bSetHigh ? uHighAccountID : uLowAccountID), + "ripple::trustCreate : matching account ID"); auto const slePeer = view.peek(keylet::account(bSetHigh ? uLowAccountID : uHighAccountID)); if (!slePeer) @@ -1052,17 +1058,25 @@ rippleCreditIOU( Currency const& currency = saAmount.getCurrency(); // Make sure issuer is involved. - assert(!bCheckIssuer || uSenderID == issuer || uReceiverID == issuer); + ASSERT( + !bCheckIssuer || uSenderID == issuer || uReceiverID == issuer, + "ripple::rippleCreditIOU : matching issuer or don't care"); (void)issuer; // Disallow sending to self. - assert(uSenderID != uReceiverID); + ASSERT( + uSenderID != uReceiverID, + "ripple::rippleCreditIOU : sender is not receiver"); bool const bSenderHigh = uSenderID > uReceiverID; auto const index = keylet::line(uSenderID, uReceiverID, currency); - assert(!isXRP(uSenderID) && uSenderID != noAccount()); - assert(!isXRP(uReceiverID) && uReceiverID != noAccount()); + ASSERT( + !isXRP(uSenderID) && uSenderID != noAccount(), + "ripple::rippleCreditIOU : sender is not XRP"); + ASSERT( + !isXRP(uReceiverID) && uReceiverID != noAccount(), + "ripple::rippleCreditIOU : receiver is not XRP"); // If the line exists, modify it accordingly. if (auto const sleRippleState = view.peek(index)) @@ -1196,8 +1210,12 @@ rippleSendIOU( { auto const issuer = saAmount.getIssuer(); - assert(!isXRP(uSenderID) && !isXRP(uReceiverID)); - assert(uSenderID != uReceiverID); + ASSERT( + !isXRP(uSenderID) && !isXRP(uReceiverID), + "ripple::rippleSendIOU : neither sender nor receiver is XRP"); + ASSERT( + uSenderID != uReceiverID, + "ripple::rippleSendIOU : sender is not receiver"); if (uSenderID == issuer || uReceiverID == issuer || issuer == noAccount()) { @@ -1250,7 +1268,9 @@ accountSendIOU( } else { - assert(saAmount >= beast::zero && !saAmount.holds()); + ASSERT( + saAmount >= beast::zero && !saAmount.holds(), + "ripple::accountSendIOU : minimum amount and not MPT"); } /* If we aren't sending anything or if the sender is the same as the @@ -1420,7 +1440,9 @@ rippleSendMPT( beast::Journal j, WaiveTransferFee waiveFee) { - assert(uSenderID != uReceiverID); + ASSERT( + uSenderID != uReceiverID, + "ripple::rippleSendMPT : sender is not receiver"); // Safe to get MPT since rippleSendMPT is only called by accountSendMPT auto const issuer = saAmount.getIssuer(); @@ -1483,7 +1505,9 @@ accountSendMPT( beast::Journal j, WaiveTransferFee waiveFee) { - assert(saAmount >= beast::zero && saAmount.holds()); + ASSERT( + saAmount >= beast::zero && saAmount.holds(), + "ripple::accountSendMPT : minimum amount and MPT"); /* If we aren't sending anything or if the sender is the same as the * receiver then we don't need to do anything. @@ -1579,13 +1603,15 @@ issueIOU( Issue const& issue, beast::Journal j) { - assert(!isXRP(account) && !isXRP(issue.account)); + ASSERT( + !isXRP(account) && !isXRP(issue.account), + "ripple::issueIOU : neither account nor issuer is XRP"); // Consistency check - assert(issue == amount.issue()); + ASSERT(issue == amount.issue(), "ripple::issueIOU : matching issue"); // Can't send to self! - assert(issue.account != account); + ASSERT(issue.account != account, "ripple::issueIOU : not issuer account"); JLOG(j.trace()) << "issueIOU: " << to_string(account) << ": " << amount.getFullText(); @@ -1675,13 +1701,15 @@ redeemIOU( Issue const& issue, beast::Journal j) { - assert(!isXRP(account) && !isXRP(issue.account)); + ASSERT( + !isXRP(account) && !isXRP(issue.account), + "ripple::redeemIOU : neither account nor issuer is XRP"); // Consistency check - assert(issue == amount.issue()); + ASSERT(issue == amount.issue(), "ripple::redeemIOU : matching issue"); // Can't send to self! - assert(issue.account != account); + ASSERT(issue.account != account, "ripple::redeemIOU : not issuer account"); JLOG(j.trace()) << "redeemIOU: " << to_string(account) << ": " << amount.getFullText(); @@ -1745,10 +1773,10 @@ transferXRP( STAmount const& amount, beast::Journal j) { - assert(from != beast::zero); - assert(to != beast::zero); - assert(from != to); - assert(amount.native()); + ASSERT(from != beast::zero, "ripple::transferXRP : nonzero from account"); + ASSERT(to != beast::zero, "ripple::transferXRP : nonzero to account"); + ASSERT(from != to, "ripple::transferXRP : sender is not receiver"); + ASSERT(amount.native(), "ripple::transferXRP : amount is XRP"); SLE::pointer const sender = view.peek(keylet::account(from)); SLE::pointer const receiver = view.peek(keylet::account(to)); @@ -1911,7 +1939,9 @@ cleanupOnAccountDelete( // // 3. So we verify that uDirEntry is indeed 'it'+1. Then we jam it // back to 'it' to "un-invalidate" the iterator. - assert(uDirEntry >= 1); + ASSERT( + uDirEntry >= 1, + "ripple::cleanupOnAccountDelete : minimum dir entries"); if (uDirEntry == 0) { JLOG(j.error()) @@ -1995,7 +2025,9 @@ rippleCredit( } else { - assert(!bCheckIssuer); + ASSERT( + !bCheckIssuer, + "ripple::rippleCredit : not checking issuer"); return rippleCreditMPT( view, uSenderID, uReceiverID, saAmount, j); } diff --git a/src/xrpld/net/detail/InfoSub.cpp b/src/xrpld/net/detail/InfoSub.cpp index 3dc891cb5f9..4d18bf0b8fa 100644 --- a/src/xrpld/net/detail/InfoSub.cpp +++ b/src/xrpld/net/detail/InfoSub.cpp @@ -145,7 +145,8 @@ InfoSub::setApiVersion(unsigned int apiVersion) unsigned int InfoSub::getApiVersion() const noexcept { - assert(apiVersion_ > 0); + ASSERT( + apiVersion_ > 0, "ripple::InfoSub::getApiVersion : valid API version"); return apiVersion_; } diff --git a/src/xrpld/net/detail/RPCCall.cpp b/src/xrpld/net/detail/RPCCall.cpp index b92f4b1a205..06989765108 100644 --- a/src/xrpld/net/detail/RPCCall.cpp +++ b/src/xrpld/net/detail/RPCCall.cpp @@ -962,7 +962,9 @@ class RPCParser parseTransactionEntry(Json::Value const& jvParams) { // Parameter count should have already been verified. - assert(jvParams.size() == 2); + ASSERT( + jvParams.size() == 2, + "ripple::RPCParser::parseTransactionEntry : valid parameter count"); std::string const txHash = jvParams[0u].asString(); if (txHash.length() != 64) diff --git a/src/xrpld/nodestore/Database.h b/src/xrpld/nodestore/Database.h index bd25046fee2..04bd718104d 100644 --- a/src/xrpld/nodestore/Database.h +++ b/src/xrpld/nodestore/Database.h @@ -246,7 +246,9 @@ class Database void storeStats(std::uint64_t count, std::uint64_t sz) { - assert(count <= sz); + ASSERT( + count <= sz, + "ripple::NodeStore::Database::storeStats : valid inputs"); storeCount_ += count; storeSz_ += sz; } diff --git a/src/xrpld/nodestore/backend/MemoryFactory.cpp b/src/xrpld/nodestore/backend/MemoryFactory.cpp index 767db9d1695..1b7bf79c81e 100644 --- a/src/xrpld/nodestore/backend/MemoryFactory.cpp +++ b/src/xrpld/nodestore/backend/MemoryFactory.cpp @@ -131,7 +131,9 @@ class MemoryBackend : public Backend Status fetch(void const* key, std::shared_ptr* pObject) override { - assert(db_); + ASSERT( + db_ != nullptr, + "ripple::NodeStore::MemoryBackend::fetch : non-null database"); uint256 const hash(uint256::fromVoid(key)); std::lock_guard _(db_->mutex); @@ -167,7 +169,9 @@ class MemoryBackend : public Backend void store(std::shared_ptr const& object) override { - assert(db_); + ASSERT( + db_ != nullptr, + "ripple::NodeStore::MemoryBackend::store : non-null database"); std::lock_guard _(db_->mutex); db_->table.emplace(object->getHash(), object); } @@ -187,7 +191,9 @@ class MemoryBackend : public Backend void for_each(std::function)> f) override { - assert(db_); + ASSERT( + db_ != nullptr, + "ripple::NodeStore::MemoryBackend::for_each : non-null database"); for (auto const& e : db_->table) f(e.second); } diff --git a/src/xrpld/nodestore/backend/NuDBFactory.cpp b/src/xrpld/nodestore/backend/NuDBFactory.cpp index 14cd84a1ad7..24ebffd33a2 100644 --- a/src/xrpld/nodestore/backend/NuDBFactory.cpp +++ b/src/xrpld/nodestore/backend/NuDBFactory.cpp @@ -23,8 +23,8 @@ #include #include #include +#include #include -#include #include #include #include @@ -117,7 +117,9 @@ class NuDBBackend : public Backend using namespace boost::filesystem; if (db_.is_open()) { - assert(false); + UNREACHABLE( + "ripple::NodeStore::NuDBBackend::open : database is already " + "open"); JLOG(j_.error()) << "database is already open"; return; } diff --git a/src/xrpld/nodestore/backend/RocksDBFactory.cpp b/src/xrpld/nodestore/backend/RocksDBFactory.cpp index 9ba9fffe1db..a4bb4ae5fb6 100644 --- a/src/xrpld/nodestore/backend/RocksDBFactory.cpp +++ b/src/xrpld/nodestore/backend/RocksDBFactory.cpp @@ -228,7 +228,9 @@ class RocksDBBackend : public Backend, public BatchWriter::Callback { if (m_db) { - assert(false); + UNREACHABLE( + "ripple::NodeStore::RocksDBBackend::open : database is already " + "open"); JLOG(m_journal.error()) << "database is already open"; return; } @@ -273,7 +275,9 @@ class RocksDBBackend : public Backend, public BatchWriter::Callback Status fetch(void const* key, std::shared_ptr* pObject) override { - assert(m_db); + ASSERT( + m_db != nullptr, + "ripple::NodeStore::RocksDBBackend::fetch : non-null database"); pObject->reset(); Status status(ok); @@ -349,7 +353,10 @@ class RocksDBBackend : public Backend, public BatchWriter::Callback void storeBatch(Batch const& batch) override { - assert(m_db); + ASSERT( + m_db != nullptr, + "ripple::NodeStore::RocksDBBackend::storeBatch : non-null " + "database"); rocksdb::WriteBatch wb; for (auto const& e : batch) @@ -381,7 +388,9 @@ class RocksDBBackend : public Backend, public BatchWriter::Callback void for_each(std::function)> f) override { - assert(m_db); + ASSERT( + m_db != nullptr, + "ripple::NodeStore::RocksDBBackend::for_each : non-null database"); rocksdb::ReadOptions const options; std::unique_ptr it(m_db->NewIterator(options)); diff --git a/src/xrpld/nodestore/detail/BatchWriter.cpp b/src/xrpld/nodestore/detail/BatchWriter.cpp index 1c5067d5bed..ec360f89f31 100644 --- a/src/xrpld/nodestore/detail/BatchWriter.cpp +++ b/src/xrpld/nodestore/detail/BatchWriter.cpp @@ -83,7 +83,9 @@ BatchWriter::writeBatch() std::lock_guard sl(mWriteMutex); mWriteSet.swap(set); - assert(mWriteSet.empty()); + ASSERT( + mWriteSet.empty(), + "ripple::NodeStore::BatchWriter::writeBatch : writes not set"); mWriteLoad = set.size(); if (set.empty()) diff --git a/src/xrpld/nodestore/detail/Database.cpp b/src/xrpld/nodestore/detail/Database.cpp index da15088e895..f9875d5062f 100644 --- a/src/xrpld/nodestore/detail/Database.cpp +++ b/src/xrpld/nodestore/detail/Database.cpp @@ -40,7 +40,9 @@ Database::Database( , requestBundle_(get(config, "rq_bundle", 4)) , readThreads_(std::max(1, readThreads)) { - assert(readThreads != 0); + ASSERT( + readThreads != 0, + "ripple::NodeStore::Database::Database : nonzero threads input"); if (earliestLedgerSeq_ < 1) Throw("Invalid earliest_seq"); @@ -87,7 +89,10 @@ Database::Database( for (auto it = read.begin(); it != read.end(); ++it) { - assert(!it->second.empty()); + ASSERT( + !it->second.empty(), + "ripple::NodeStore::Database::Database : non-empty " + "data"); auto const& hash = it->first; auto const& data = it->second; @@ -161,7 +166,9 @@ Database::stop() while (readThreads_.load() != 0) { - assert(steady_clock::now() - start < 30s); + ASSERT( + steady_clock::now() - start < 30s, + "ripple::NodeStore::Database::stop : maximum stop duration"); std::this_thread::yield(); } @@ -212,7 +219,9 @@ Database::importInternal(Backend& dstBackend, Database& srcDB) }; srcDB.for_each([&](std::shared_ptr nodeObject) { - assert(nodeObject); + ASSERT( + nodeObject != nullptr, + "ripple::NodeStore::Database::importInternal : non-null node"); if (!nodeObject) // This should never happen return; @@ -256,7 +265,9 @@ Database::fetchNodeObject( void Database::getCountsJson(Json::Value& obj) { - assert(obj.isObject()); + ASSERT( + obj.isObject(), + "ripple::NodeStore::Database::getCountsJson : valid input type"); { std::unique_lock lock(readLock_); diff --git a/src/xrpld/nodestore/detail/DatabaseNodeImp.h b/src/xrpld/nodestore/detail/DatabaseNodeImp.h index 326db38a661..2ed3443da92 100644 --- a/src/xrpld/nodestore/detail/DatabaseNodeImp.h +++ b/src/xrpld/nodestore/detail/DatabaseNodeImp.h @@ -76,7 +76,10 @@ class DatabaseNodeImp : public Database j); } - assert(backend_); + ASSERT( + backend_ != nullptr, + "ripple::NodeStore::DatabaseNodeImp::DatabaseNodeImp : non-null " + "backend"); } ~DatabaseNodeImp() diff --git a/src/xrpld/nodestore/detail/DecodedBlob.cpp b/src/xrpld/nodestore/detail/DecodedBlob.cpp index b71f2c543b1..49e1ff5e3bb 100644 --- a/src/xrpld/nodestore/detail/DecodedBlob.cpp +++ b/src/xrpld/nodestore/detail/DecodedBlob.cpp @@ -19,8 +19,8 @@ #include #include +#include #include -#include namespace ripple { namespace NodeStore { @@ -72,7 +72,9 @@ DecodedBlob::DecodedBlob(void const* key, void const* value, int valueBytes) std::shared_ptr DecodedBlob::createObject() { - assert(m_success); + ASSERT( + m_success, + "ripple::NodeStore::DecodedBlob::createObject : valid object type"); std::shared_ptr object; diff --git a/src/xrpld/nodestore/detail/EncodedBlob.h b/src/xrpld/nodestore/detail/EncodedBlob.h index 2b506a0df3f..d99908cf4f6 100644 --- a/src/xrpld/nodestore/detail/EncodedBlob.h +++ b/src/xrpld/nodestore/detail/EncodedBlob.h @@ -22,10 +22,10 @@ #include #include +#include #include #include #include -#include #include namespace ripple { @@ -80,7 +80,9 @@ class EncodedBlob public: explicit EncodedBlob(std::shared_ptr const& obj) : size_([&obj]() { - assert(obj); + ASSERT( + obj != nullptr, + "ripple::NodeStore::EncodedBlob::EncodedBlob : non-null input"); if (!obj) throw std::runtime_error( @@ -100,9 +102,11 @@ class EncodedBlob ~EncodedBlob() { - assert( + ASSERT( ((ptr_ == payload_.data()) && (size_ <= payload_.size())) || - ((ptr_ != payload_.data()) && (size_ > payload_.size()))); + ((ptr_ != payload_.data()) && (size_ > payload_.size())), + "ripple::NodeStore::EncodedBlob::~EncodedBlob : valid payload " + "pointer"); if (ptr_ != payload_.data()) delete[] ptr_; diff --git a/src/xrpld/nodestore/detail/ManagerImp.cpp b/src/xrpld/nodestore/detail/ManagerImp.cpp index 56dc66ee644..38f193a7d8a 100644 --- a/src/xrpld/nodestore/detail/ManagerImp.cpp +++ b/src/xrpld/nodestore/detail/ManagerImp.cpp @@ -91,7 +91,9 @@ ManagerImp::erase(Factory& factory) std::find_if(list_.begin(), list_.end(), [&factory](Factory* other) { return other == &factory; }); - assert(iter != list_.end()); + ASSERT( + iter != list_.end(), + "ripple::NodeStore::ManagerImp::erase : valid input"); list_.erase(iter); } diff --git a/src/xrpld/overlay/Compression.h b/src/xrpld/overlay/Compression.h index 1cf13fcb185..c7437badc4d 100644 --- a/src/xrpld/overlay/Compression.h +++ b/src/xrpld/overlay/Compression.h @@ -64,7 +64,9 @@ decompress( JLOG(debugLog().warn()) << "decompress: invalid compression algorithm " << static_cast(algorithm); - assert(0); + UNREACHABLE( + "ripple::compression::decompress : invalid compression " + "algorithm"); } } catch (...) @@ -99,7 +101,9 @@ compress( { JLOG(debugLog().warn()) << "compress: invalid compression algorithm" << static_cast(algorithm); - assert(0); + UNREACHABLE( + "ripple::compression::compress : invalid compression " + "algorithm"); } } catch (...) diff --git a/src/xrpld/overlay/Slot.h b/src/xrpld/overlay/Slot.h index 2a8b2146a02..fca6c621fa0 100644 --- a/src/xrpld/overlay/Slot.h +++ b/src/xrpld/overlay/Slot.h @@ -362,7 +362,9 @@ Slot::update( << consideredPoolSize << " selected " << *s << " " << *std::next(s, 1) << " " << *std::next(s, 2); - assert(peers_.size() >= MAX_SELECTED_PEERS); + ASSERT( + peers_.size() >= MAX_SELECTED_PEERS, + "ripple::reduce_relay::Slot::update : minimum peers"); // squelch peers which are not selected and // not already squelched diff --git a/src/xrpld/overlay/detail/ConnectAttempt.cpp b/src/xrpld/overlay/detail/ConnectAttempt.cpp index 6a3ebdd5b98..d65366560d5 100644 --- a/src/xrpld/overlay/detail/ConnectAttempt.cpp +++ b/src/xrpld/overlay/detail/ConnectAttempt.cpp @@ -90,7 +90,9 @@ ConnectAttempt::run() void ConnectAttempt::close() { - assert(strand_.running_in_this_thread()); + ASSERT( + strand_.running_in_this_thread(), + "ripple::ConnectAttempt::close : strand in this thread"); if (socket_.is_open()) { error_code ec; diff --git a/src/xrpld/overlay/detail/Message.cpp b/src/xrpld/overlay/detail/Message.cpp index 71917db0506..6e44f3e957c 100644 --- a/src/xrpld/overlay/detail/Message.cpp +++ b/src/xrpld/overlay/detail/Message.cpp @@ -34,7 +34,9 @@ Message::Message( auto const messageBytes = messageSize(message); - assert(messageBytes != 0); + ASSERT( + messageBytes != 0, + "ripple::Message::Message : non-empty message input"); buffer_.resize(headerBytes + messageBytes); @@ -43,7 +45,9 @@ Message::Message( if (messageBytes != 0) message.SerializeToArray(buffer_.data() + headerBytes, messageBytes); - assert(getBufferSize() == totalSize(message)); + ASSERT( + getBufferSize() == totalSize(message), + "ripple::Message::Message : message size matches the buffer"); } // static diff --git a/src/xrpld/overlay/detail/OverlayImpl.cpp b/src/xrpld/overlay/detail/OverlayImpl.cpp index e41a08a43d1..d5bd6e2ce68 100644 --- a/src/xrpld/overlay/detail/OverlayImpl.cpp +++ b/src/xrpld/overlay/detail/OverlayImpl.cpp @@ -294,7 +294,9 @@ OverlayImpl::onHandoff( std::lock_guard lock(mutex_); { auto const result = m_peers.emplace(peer->slot(), peer); - assert(result.second); + ASSERT( + result.second, + "ripple::OverlayImpl::onHandoff : peer is inserted"); (void)result.second; } list_.emplace(peer.get(), peer); @@ -387,7 +389,7 @@ OverlayImpl::makeErrorResponse( void OverlayImpl::connect(beast::IP::Endpoint const& remote_endpoint) { - assert(work_); + ASSERT(work_.has_value(), "ripple::OverlayImpl::connect : work is set"); auto usage = resourceManager().newOutboundEndpoint(remote_endpoint); if (usage.disconnect(journal_)) @@ -429,7 +431,9 @@ OverlayImpl::add_active(std::shared_ptr const& peer) { auto const result = m_peers.emplace(peer->slot(), peer); - assert(result.second); + ASSERT( + result.second, + "ripple::OverlayImpl::add_active : peer is inserted"); (void)result.second; } @@ -438,7 +442,9 @@ OverlayImpl::add_active(std::shared_ptr const& peer) std::piecewise_construct, std::make_tuple(peer->id()), std::make_tuple(peer)); - assert(result.second); + ASSERT( + result.second, + "ripple::OverlayImpl::add_active : peer ID is inserted"); (void)result.second; } @@ -461,7 +467,7 @@ OverlayImpl::remove(std::shared_ptr const& slot) { std::lock_guard lock(mutex_); auto const iter = m_peers.find(slot); - assert(iter != m_peers.end()); + ASSERT(iter != m_peers.end(), "ripple::OverlayImpl::remove : valid input"); m_peers.erase(iter); } @@ -598,7 +604,9 @@ OverlayImpl::activate(std::shared_ptr const& peer) std::piecewise_construct, std::make_tuple(peer->id()), std::make_tuple(peer))); - assert(result.second); + ASSERT( + result.second, + "ripple::OverlayImpl::activate : peer ID is inserted"); (void)result.second; } @@ -609,7 +617,7 @@ OverlayImpl::activate(std::shared_ptr const& peer) << ")"; // We just accepted this peer so we have non-zero active peers - assert(size() != 0); + ASSERT(size() != 0, "ripple::OverlayImpl::activate : nonzero peers"); } void @@ -648,7 +656,10 @@ OverlayImpl::onManifests( // the loaded Manifest out of the optional so we need to // reload it here. mo = deserializeManifest(serialized); - assert(mo); + ASSERT( + mo.has_value(), + "ripple::OverlayImpl::onManifests : manifest " + "deserialization succeeded"); app_.getOPs().pubManifest(*mo); diff --git a/src/xrpld/overlay/detail/OverlayImpl.h b/src/xrpld/overlay/detail/OverlayImpl.h index a50dfc5e905..63e002ddf79 100644 --- a/src/xrpld/overlay/detail/OverlayImpl.h +++ b/src/xrpld/overlay/detail/OverlayImpl.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -41,7 +42,6 @@ #include #include #include -#include #include #include #include @@ -600,7 +600,9 @@ class OverlayImpl : public Overlay, public reduce_relay::SquelchHandler { auto counts = m_traffic.getCounts(); std::lock_guard lock(m_statsMutex); - assert(counts.size() == m_stats.trafficGauges.size()); + ASSERT( + counts.size() == m_stats.trafficGauges.size(), + "ripple::OverlayImpl::collect_metrics : counts size do match"); for (std::size_t i = 0; i < counts.size(); ++i) { diff --git a/src/xrpld/overlay/detail/PeerImp.cpp b/src/xrpld/overlay/detail/PeerImp.cpp index 4f5f1470f8e..5dd64c27ea5 100644 --- a/src/xrpld/overlay/detail/PeerImp.cpp +++ b/src/xrpld/overlay/detail/PeerImp.cpp @@ -565,7 +565,9 @@ PeerImp::hasRange(std::uint32_t uMin, std::uint32_t uMax) void PeerImp::close() { - assert(strand_.running_in_this_thread()); + ASSERT( + strand_.running_in_this_thread(), + "ripple::PeerImp::close : strand in this thread"); if (socket_.is_open()) { detaching_ = true; // DEPRECATED @@ -606,7 +608,9 @@ PeerImp::fail(std::string const& reason) void PeerImp::fail(std::string const& name, error_code ec) { - assert(strand_.running_in_this_thread()); + ASSERT( + strand_.running_in_this_thread(), + "ripple::PeerImp::fail : strand in this thread"); if (socket_.is_open()) { JLOG(journal_.warn()) @@ -619,9 +623,14 @@ PeerImp::fail(std::string const& name, error_code ec) void PeerImp::gracefulClose() { - assert(strand_.running_in_this_thread()); - assert(socket_.is_open()); - assert(!gracefulClose_); + ASSERT( + strand_.running_in_this_thread(), + "ripple::PeerImp::gracefulClose : strand in this thread"); + ASSERT( + socket_.is_open(), "ripple::PeerImp::gracefulClose : socket is open"); + ASSERT( + !gracefulClose_, + "ripple::PeerImp::gracefulClose : socket is not closing"); gracefulClose_ = true; if (send_queue_.size() > 0) return; @@ -747,7 +756,9 @@ PeerImp::onShutdown(error_code ec) void PeerImp::doAccept() { - assert(read_buffer_.size() == 0); + ASSERT( + read_buffer_.size() == 0, + "ripple::PeerImp::doAccept : empty read buffer"); JLOG(journal_.debug()) << "doAccept: " << remote_address_; @@ -948,7 +959,9 @@ PeerImp::onWriteMessage(error_code ec, std::size_t bytes_transferred) metrics_.sent.add_message(bytes_transferred); - assert(!send_queue_.empty()); + ASSERT( + !send_queue_.empty(), + "ripple::PeerImp::onWriteMessage : non-empty send buffer"); send_queue_.pop(); if (!send_queue_.empty()) { @@ -2002,13 +2015,18 @@ PeerImp::onValidatorListMessage( case ListDisposition::pending: { std::lock_guard sl(recentLock_); - assert(applyResult.publisherKey); + ASSERT( + applyResult.publisherKey.has_value(), + "ripple::PeerImp::onValidatorListMessage : publisher key is " + "set"); auto const& pubKey = *applyResult.publisherKey; #ifndef NDEBUG if (auto const iter = publisherListSequences_.find(pubKey); iter != publisherListSequences_.end()) { - assert(iter->second < applyResult.sequence); + ASSERT( + iter->second < applyResult.sequence, + "ripple::PeerImp::onValidatorListMessage : lower sequence"); } #endif publisherListSequences_[pubKey] = applyResult.sequence; @@ -2019,10 +2037,14 @@ PeerImp::onValidatorListMessage( #ifndef NDEBUG { std::lock_guard sl(recentLock_); - assert(applyResult.sequence && applyResult.publisherKey); - assert( + ASSERT( + applyResult.sequence && applyResult.publisherKey, + "ripple::PeerImp::onValidatorListMessage : nonzero sequence " + "and set publisher key"); + ASSERT( publisherListSequences_[*applyResult.publisherKey] <= - applyResult.sequence); + applyResult.sequence, + "ripple::PeerImp::onValidatorListMessage : maximum sequence"); } #endif // !NDEBUG @@ -2033,7 +2055,9 @@ PeerImp::onValidatorListMessage( case ListDisposition::unsupported_version: break; default: - assert(false); + UNREACHABLE( + "ripple::PeerImp::onValidatorListMessage : invalid best list " + "disposition"); } // Charge based on the worst result @@ -2072,7 +2096,9 @@ PeerImp::onValidatorListMessage( fee_ = Resource::feeBadData; break; default: - assert(false); + UNREACHABLE( + "ripple::PeerImp::onValidatorListMessage : invalid worst list " + "disposition"); } // Log based on all the results. @@ -2130,7 +2156,9 @@ PeerImp::onValidatorListMessage( << "(s) from peer " << remote_address_; break; default: - assert(false); + UNREACHABLE( + "ripple::PeerImp::onValidatorListMessage : invalid list " + "disposition"); } } } @@ -2805,7 +2833,8 @@ PeerImp::checkPropose( JLOG(p_journal_.trace()) << "Checking " << (isTrusted ? "trusted" : "UNTRUSTED") << " proposal"; - assert(packet); + ASSERT( + packet != nullptr, "ripple::PeerImp::checkPropose : non-null packet"); if (!cluster() && !peerPos.checkSign()) { diff --git a/src/xrpld/overlay/detail/ProtocolMessage.h b/src/xrpld/overlay/detail/ProtocolMessage.h index 8a7512afb31..b1e871437f3 100644 --- a/src/xrpld/overlay/detail/ProtocolMessage.h +++ b/src/xrpld/overlay/detail/ProtocolMessage.h @@ -24,11 +24,11 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include @@ -175,7 +175,9 @@ parseMessageHeader( MessageHeader hdr; auto iter = buffersBegin(bufs); - assert(iter != buffersEnd(bufs)); + ASSERT( + iter != buffersEnd(bufs), + "ripple::detail::parseMessageHeader : non-empty buffer"); // Check valid header compressed message: // - 4 bits are the compression algorithm, 1st bit is always set to 1 diff --git a/src/xrpld/overlay/detail/TrafficCount.h b/src/xrpld/overlay/detail/TrafficCount.h index 7dd5cbba901..754e2872b18 100644 --- a/src/xrpld/overlay/detail/TrafficCount.h +++ b/src/xrpld/overlay/detail/TrafficCount.h @@ -21,6 +21,7 @@ #define RIPPLE_OVERLAY_TRAFFIC_H_INCLUDED #include +#include #include #include @@ -171,7 +172,9 @@ class TrafficCount void addCount(category cat, bool inbound, int bytes) { - assert(cat <= category::unknown); + ASSERT( + cat <= category::unknown, + "ripple::TrafficCount::addCount : valid category input"); if (inbound) { diff --git a/src/xrpld/overlay/detail/ZeroCopyStream.h b/src/xrpld/overlay/detail/ZeroCopyStream.h index da0f0d380d8..44d8100952e 100644 --- a/src/xrpld/overlay/detail/ZeroCopyStream.h +++ b/src/xrpld/overlay/detail/ZeroCopyStream.h @@ -20,6 +20,8 @@ #ifndef RIPPLE_OVERLAY_ZEROCOPYSTREAM_H_INCLUDED #define RIPPLE_OVERLAY_ZEROCOPYSTREAM_H_INCLUDED +#include + #include #include #include @@ -204,7 +206,8 @@ template void ZeroCopyOutputStream::BackUp(int count) { - assert(count <= commit_); + ASSERT( + count <= commit_, "ripple::ZeroCopyOutputStream::BackUp : valid input"); auto const n = commit_ - count; streambuf_.commit(n); count_ += n; diff --git a/src/xrpld/peerfinder/detail/Bootcache.cpp b/src/xrpld/peerfinder/detail/Bootcache.cpp index 9e94a12e619..88fa4c6221a 100644 --- a/src/xrpld/peerfinder/detail/Bootcache.cpp +++ b/src/xrpld/peerfinder/detail/Bootcache.cpp @@ -159,7 +159,9 @@ Bootcache::on_success(beast::IP::Endpoint const& endpoint) ++entry.valence(); m_map.erase(result.first); result = m_map.insert(value_type(endpoint, entry)); - assert(result.second); + ASSERT( + result.second, + "ripple:PeerFinder::Bootcache::on_success : endpoint inserted"); } Entry const& entry(result.first->right); JLOG(m_journal.info()) << beast::leftw(18) << "Bootcache connect " @@ -185,7 +187,9 @@ Bootcache::on_failure(beast::IP::Endpoint const& endpoint) --entry.valence(); m_map.erase(result.first); result = m_map.insert(value_type(endpoint, entry)); - assert(result.second); + ASSERT( + result.second, + "ripple:PeerFinder::Bootcache::on_failure : endpoint inserted"); } Entry const& entry(result.first->right); auto const n(std::abs(entry.valence())); diff --git a/src/xrpld/peerfinder/detail/Counts.h b/src/xrpld/peerfinder/detail/Counts.h index 1ea6ff976de..d18aa858567 100644 --- a/src/xrpld/peerfinder/detail/Counts.h +++ b/src/xrpld/peerfinder/detail/Counts.h @@ -71,7 +71,9 @@ class Counts can_activate(Slot const& s) const { // Must be handshaked and in the right state - assert(s.state() == Slot::connected || s.state() == Slot::accept); + ASSERT( + s.state() == Slot::connected || s.state() == Slot::accept, + "ripple::PeerFinder::Counts::can_activate : valid input state"); if (s.fixed() || s.reserved()) return true; @@ -262,13 +264,18 @@ class Counts switch (s.state()) { case Slot::accept: - assert(s.inbound()); + ASSERT( + s.inbound(), + "ripple::PeerFinder::Counts::adjust : input is inbound"); m_acceptCount += n; break; case Slot::connect: case Slot::connected: - assert(!s.inbound()); + ASSERT( + !s.inbound(), + "ripple::PeerFinder::Counts::adjust : input is not " + "inbound"); m_attempts += n; break; @@ -290,7 +297,8 @@ class Counts break; default: - assert(false); + UNREACHABLE( + "ripple::PeerFinder::Counts::adjust : invalid input state"); break; }; } diff --git a/src/xrpld/peerfinder/detail/Handouts.h b/src/xrpld/peerfinder/detail/Handouts.h index 0b54dc205fa..aa397d79c6e 100644 --- a/src/xrpld/peerfinder/detail/Handouts.h +++ b/src/xrpld/peerfinder/detail/Handouts.h @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include @@ -43,7 +43,9 @@ template std::size_t handout_one(Target& t, HopContainer& h) { - assert(!t.full()); + ASSERT( + !t.full(), + "ripple::PeerFinder::detail::handout_one : target is not full"); for (auto it = h.begin(); it != h.end(); ++it) { auto const& e = *it; diff --git a/src/xrpld/peerfinder/detail/Livecache.h b/src/xrpld/peerfinder/detail/Livecache.h index 1583ccd96a3..bf1aca2eb9d 100644 --- a/src/xrpld/peerfinder/detail/Livecache.h +++ b/src/xrpld/peerfinder/detail/Livecache.h @@ -432,7 +432,9 @@ Livecache::insert(Endpoint const& ep) // but we will use it to make connections and hand it out // when redirecting. // - assert(ep.hops <= (Tuning::maxHops + 1)); + ASSERT( + ep.hops <= (Tuning::maxHops + 1), + "ripple::PeerFinder::Livecache::insert : maximum input hops"); auto result = m_cache.emplace(ep.address, ep); Element& e(result.first->second); if (result.second) @@ -530,7 +532,9 @@ template void Livecache::hops_t::insert(Element& e) { - assert(e.endpoint.hops <= Tuning::maxHops + 1); + ASSERT( + e.endpoint.hops <= Tuning::maxHops + 1, + "ripple::PeerFinder::Livecache::hops_t::insert : maximum input hops"); // This has security implications without a shuffle m_lists[e.endpoint.hops].push_front(e); ++m_hist[e.endpoint.hops]; @@ -540,7 +544,9 @@ template void Livecache::hops_t::reinsert(Element& e, std::uint32_t numHops) { - assert(numHops <= Tuning::maxHops + 1); + ASSERT( + numHops <= Tuning::maxHops + 1, + "ripple::PeerFinder::Livecache::hops_t::reinsert : maximum hops input"); auto& list = m_lists[e.endpoint.hops]; list.erase(list.iterator_to(e)); diff --git a/src/xrpld/peerfinder/detail/Logic.h b/src/xrpld/peerfinder/detail/Logic.h index 3bfb9942c3a..41bb6789a86 100644 --- a/src/xrpld/peerfinder/detail/Logic.h +++ b/src/xrpld/peerfinder/detail/Logic.h @@ -304,7 +304,10 @@ class Logic // Add slot to table auto const result(slots_.emplace(slot->remote_endpoint(), slot)); // Remote address must not already exist - assert(result.second); + ASSERT( + result.second, + "ripple::PeerFinder::Logic::new_inbound_slot : remote endpoint " + "inserted"); // Add to the connected address list connectedAddresses_.emplace(remote_endpoint.address()); @@ -339,7 +342,10 @@ class Logic // Add slot to table auto const result = slots_.emplace(slot->remote_endpoint(), slot); // Remote address must not already exist - assert(result.second); + ASSERT( + result.second, + "ripple::PeerFinder::Logic::new_outbound_slot : remote endpoint " + "inserted"); // Add to the connected address list connectedAddresses_.emplace(remote_endpoint.address()); @@ -362,7 +368,9 @@ class Logic std::lock_guard _(lock_); // The object must exist in our table - assert(slots_.find(slot->remote_endpoint()) != slots_.end()); + ASSERT( + slots_.find(slot->remote_endpoint()) != slots_.end(), + "ripple::PeerFinder::Logic::onConnected : valid slot input"); // Assign the local endpoint now that it's known slot->local_endpoint(local_endpoint); @@ -371,8 +379,10 @@ class Logic auto const iter(slots_.find(local_endpoint)); if (iter != slots_.end()) { - assert( - iter->second->local_endpoint() == slot->remote_endpoint()); + ASSERT( + iter->second->local_endpoint() == slot->remote_endpoint(), + "ripple::PeerFinder::Logic::onConnected : local and remote " + "endpoints do match"); JLOG(m_journal.warn()) << beast::leftw(18) << "Logic dropping " << slot->remote_endpoint() << " as self connect"; @@ -397,10 +407,13 @@ class Logic std::lock_guard _(lock_); // The object must exist in our table - assert(slots_.find(slot->remote_endpoint()) != slots_.end()); + ASSERT( + slots_.find(slot->remote_endpoint()) != slots_.end(), + "ripple::PeerFinder::Logic::activate : valid slot input"); // Must be accepted or connected - assert( - slot->state() == Slot::accept || slot->state() == Slot::connected); + ASSERT( + slot->state() == Slot::accept || slot->state() == Slot::connected, + "ripple::PeerFinder::Logic::activate : valid slot state"); // Check for duplicate connection by key if (keys_.find(key) != keys_.end()) @@ -426,7 +439,9 @@ class Logic { [[maybe_unused]] bool const inserted = keys_.insert(key).second; // Public key must not already exist - assert(inserted); + ASSERT( + inserted, + "ripple::PeerFinder::Logic::activate : public key inserted"); } // Change state and update counts @@ -788,10 +803,14 @@ class Logic std::lock_guard _(lock_); // The object must exist in our table - assert(slots_.find(slot->remote_endpoint()) != slots_.end()); + ASSERT( + slots_.find(slot->remote_endpoint()) != slots_.end(), + "ripple::PeerFinder::Logic::on_endpoints : valid slot input"); // Must be handshaked! - assert(slot->state() == Slot::active); + ASSERT( + slot->state() == Slot::active, + "ripple::PeerFinder::Logic::on_endpoints : valid slot state"); clock_type::time_point const now(m_clock.now()); @@ -803,7 +822,9 @@ class Logic for (auto const& ep : list) { - assert(ep.hops != 0); + ASSERT( + ep.hops != 0, + "ripple::PeerFinder::Logic::on_endpoints : nonzero hops"); slot->recent.insert(ep.address, ep.hops); @@ -956,7 +977,9 @@ class Logic break; default: - assert(false); + UNREACHABLE( + "ripple::PeerFinder::Logic::on_closed : invalid slot " + "state"); break; } } diff --git a/src/xrpld/peerfinder/detail/SlotImp.cpp b/src/xrpld/peerfinder/detail/SlotImp.cpp index a5d13aa729e..4cc3e577d66 100644 --- a/src/xrpld/peerfinder/detail/SlotImp.cpp +++ b/src/xrpld/peerfinder/detail/SlotImp.cpp @@ -64,19 +64,32 @@ void SlotImp::state(State state_) { // Must go through activate() to set active state - assert(state_ != active); + ASSERT( + state_ != active, + "ripple::PeerFinder::SlotImp::state : input state is not active"); // The state must be different - assert(state_ != m_state); + ASSERT( + state_ != m_state, + "ripple::PeerFinder::SlotImp::state : input state is different from " + "current"); // You can't transition into the initial states - assert(state_ != accept && state_ != connect); + ASSERT( + state_ != accept && state_ != connect, + "ripple::PeerFinder::SlotImp::state : input state is not an initial"); // Can only become connected from outbound connect state - assert(state_ != connected || (!m_inbound && m_state == connect)); + ASSERT( + state_ != connected || (!m_inbound && m_state == connect), + "ripple::PeerFinder::SlotImp::state : input state is not connected an " + "invalid state"); // Can't gracefully close on an outbound connection attempt - assert(state_ != closing || m_state != connect); + ASSERT( + state_ != closing || m_state != connect, + "ripple::PeerFinder::SlotImp::state : input state is not closing an " + "invalid state"); m_state = state_; } @@ -85,7 +98,9 @@ void SlotImp::activate(clock_type::time_point const& now) { // Can only become active from the accept or connected state - assert(m_state == accept || m_state == connected); + ASSERT( + m_state == accept || m_state == connected, + "ripple::PeerFinder::SlotImp::activate : valid state"); m_state = active; whenAcceptEndpoints = now; diff --git a/src/xrpld/perflog/detail/PerfLogImp.cpp b/src/xrpld/perflog/detail/PerfLogImp.cpp index a4773b33e10..559bdb1743c 100644 --- a/src/xrpld/perflog/detail/PerfLogImp.cpp +++ b/src/xrpld/perflog/detail/PerfLogImp.cpp @@ -54,7 +54,9 @@ PerfLogImp::Counters::Counters( if (!inserted) { // Ensure that no other function populates this entry. - assert(false); + UNREACHABLE( + "ripple::perf::PerfLogImp::Counters::Counters : failed to " + "insert label"); } } } @@ -67,7 +69,9 @@ PerfLogImp::Counters::Counters( if (!inserted) { // Ensure that no other function populates this entry. - assert(false); + UNREACHABLE( + "ripple::perf::PerfLogImp::Counters::Counters : failed to " + "insert job type"); } } } @@ -326,7 +330,7 @@ PerfLogImp::rpcStart(std::string const& method, std::uint64_t const requestId) auto counter = counters_.rpc_.find(method); if (counter == counters_.rpc_.end()) { - assert(false); + UNREACHABLE("ripple::perf::PerfLogImp::rpcStart : valid method input"); return; } @@ -348,7 +352,7 @@ PerfLogImp::rpcEnd( auto counter = counters_.rpc_.find(method); if (counter == counters_.rpc_.end()) { - assert(false); + UNREACHABLE("ripple::perf::PerfLogImp::rpcEnd : valid method input"); return; } steady_time_point startTime; @@ -362,7 +366,8 @@ PerfLogImp::rpcEnd( } else { - assert(false); + UNREACHABLE( + "ripple::perf::PerfLogImp::rpcEnd : valid requestId input"); } } std::lock_guard lock(counter->second.mutex); @@ -380,7 +385,8 @@ PerfLogImp::jobQueue(JobType const type) auto counter = counters_.jq_.find(type); if (counter == counters_.jq_.end()) { - assert(false); + UNREACHABLE( + "ripple::perf::PerfLogImp::jobQueue : valid job type input"); return; } std::lock_guard lock(counter->second.mutex); @@ -397,7 +403,8 @@ PerfLogImp::jobStart( auto counter = counters_.jq_.find(type); if (counter == counters_.jq_.end()) { - assert(false); + UNREACHABLE( + "ripple::perf::PerfLogImp::jobStart : valid job type input"); return; } { @@ -416,7 +423,8 @@ PerfLogImp::jobFinish(JobType const type, microseconds dur, int instance) auto counter = counters_.jq_.find(type); if (counter == counters_.jq_.end()) { - assert(false); + UNREACHABLE( + "ripple::perf::PerfLogImp::jobFinish : valid job type input"); return; } { diff --git a/src/xrpld/rpc/Status.h b/src/xrpld/rpc/Status.h index 1d94a6837a8..34ca69e9576 100644 --- a/src/xrpld/rpc/Status.h +++ b/src/xrpld/rpc/Status.h @@ -20,9 +20,9 @@ #ifndef RIPPLE_RPC_STATUS_H_INCLUDED #define RIPPLE_RPC_STATUS_H_INCLUDED +#include #include #include -#include namespace ripple { namespace RPC { @@ -95,7 +95,7 @@ struct Status : public std::exception TER toTER() const { - assert(type_ == Type::TER); + ASSERT(type_ == Type::TER, "ripple::RPC::Status::toTER : type is TER"); return TER::fromInt(code_); } @@ -104,7 +104,9 @@ struct Status : public std::exception error_code_i toErrorCode() const { - assert(type_ == Type::error_code_i); + ASSERT( + type_ == Type::error_code_i, + "ripple::RPC::Status::toTER : type is error code"); return error_code_i(code_); } diff --git a/src/xrpld/rpc/detail/Handler.cpp b/src/xrpld/rpc/detail/Handler.cpp index 90dee4475a1..f303f657172 100644 --- a/src/xrpld/rpc/detail/Handler.cpp +++ b/src/xrpld/rpc/detail/Handler.cpp @@ -38,7 +38,7 @@ byRef(Function const& f) result = f(context); if (result.type() != Json::objectValue) { - assert(false); + UNREACHABLE("ripple::RPC::byRef : result is object"); result = RPC::makeObjectValue(result); } @@ -50,9 +50,10 @@ template Status handle(JsonContext& context, Object& object) { - assert( + ASSERT( context.apiVersion >= HandlerImpl::minApiVer && - context.apiVersion <= HandlerImpl::maxApiVer); + context.apiVersion <= HandlerImpl::maxApiVer, + "ripple::RPC::handle : valid API version"); HandlerImpl handler(context); auto status = handler.check(); @@ -204,8 +205,12 @@ class HandlerTable unsigned minVer, unsigned maxVer) { - assert(minVer <= maxVer); - assert(maxVer <= RPC::apiMaximumValidVersion); + ASSERT( + minVer <= maxVer, + "ripple::RPC::HandlerTable : valid API version range"); + ASSERT( + maxVer <= RPC::apiMaximumValidVersion, + "ripple::RPC::HandlerTable : valid max API version"); return std::any_of( range.first, diff --git a/src/xrpld/rpc/detail/RPCHelpers.cpp b/src/xrpld/rpc/detail/RPCHelpers.cpp index af204eaedf7..6ab8cee27e2 100644 --- a/src/xrpld/rpc/detail/RPCHelpers.cpp +++ b/src/xrpld/rpc/detail/RPCHelpers.cpp @@ -544,19 +544,21 @@ getLedger(T& ledger, LedgerShortcut shortcut, Context& context) return {rpcNOT_SYNCED, "notSynced"}; } - assert(!ledger->open()); + ASSERT( + !ledger->open(), "ripple::RPC::getLedger : validated is not open"); } else { if (shortcut == LedgerShortcut::CURRENT) { ledger = context.ledgerMaster.getCurrentLedger(); - assert(ledger->open()); + ASSERT(ledger->open(), "ripple::RPC::getLedger : current is open"); } else if (shortcut == LedgerShortcut::CLOSED) { ledger = context.ledgerMaster.getClosedLedger(); - assert(!ledger->open()); + ASSERT( + !ledger->open(), "ripple::RPC::getLedger : closed is not open"); } else { @@ -965,7 +967,9 @@ chooseLedgerEntryType(Json::Value const& params) { result.first = RPC::Status{ rpcINVALID_PARAMS, "Invalid field 'type', not string."}; - assert(result.first.type() == RPC::Status::Type::error_code_i); + ASSERT( + result.first.type() == RPC::Status::Type::error_code_i, + "ripple::RPC::chooseLedgerEntryType : first valid result type"); return result; } @@ -978,7 +982,10 @@ chooseLedgerEntryType(Json::Value const& params) { result.first = RPC::Status{rpcINVALID_PARAMS, "Invalid field 'type'."}; - assert(result.first.type() == RPC::Status::Type::error_code_i); + ASSERT( + result.first.type() == RPC::Status::Type::error_code_i, + "ripple::RPC::chooseLedgerEntryType : second valid result " + "type"); return result; } result.second = iter->second; @@ -1084,7 +1091,9 @@ getLedgerByContext(RPC::JsonContext& context) // ledger auto const refIndex = getCandidateLedger(ledgerIndex); auto refHash = hashOfSeq(*ledger, refIndex, j); - assert(refHash); + ASSERT( + refHash.has_value(), + "ripple::RPC::getLedgerByContext : nonzero ledger hash"); ledger = ledgerMaster.getLedgerByHash(*refHash); if (!ledger) @@ -1118,7 +1127,9 @@ getLedgerByContext(RPC::JsonContext& context) neededHash = hashOfSeq(*ledger, ledgerIndex, j); } - assert(neededHash); + ASSERT( + neededHash.has_value(), + "ripple::RPC::getLedgerByContext : nonzero needed hash"); ledgerHash = neededHash ? *neededHash : beast::zero; // kludge } diff --git a/src/xrpld/rpc/detail/RPCHelpers.h b/src/xrpld/rpc/detail/RPCHelpers.h index 54c426b17c3..80ab9d6a5ec 100644 --- a/src/xrpld/rpc/detail/RPCHelpers.h +++ b/src/xrpld/rpc/detail/RPCHelpers.h @@ -213,7 +213,9 @@ template void setVersion(Object& parent, unsigned int apiVersion, bool betaEnabled) { - assert(apiVersion != apiInvalidVersion); + ASSERT( + apiVersion != apiInvalidVersion, + "ripple::RPC::setVersion : input is valid"); auto&& object = addObject(parent, jss::version); if (apiVersion == apiVersionIfUnspecified) { diff --git a/src/xrpld/rpc/detail/Role.cpp b/src/xrpld/rpc/detail/Role.cpp index 5cfe30b26e6..739c8f58012 100644 --- a/src/xrpld/rpc/detail/Role.cpp +++ b/src/xrpld/rpc/detail/Role.cpp @@ -28,7 +28,9 @@ namespace ripple { bool passwordUnrequiredOrSentCorrect(Port const& port, Json::Value const& params) { - assert(!(port.admin_nets_v4.empty() && port.admin_nets_v6.empty())); + ASSERT( + !(port.admin_nets_v4.empty() && port.admin_nets_v6.empty()), + "ripple::passwordUnrequiredOrSentCorrect : non-empty admin nets"); bool const passwordRequired = (!port.admin_user.empty() || !port.admin_password.empty()); diff --git a/src/xrpld/rpc/detail/Status.cpp b/src/xrpld/rpc/detail/Status.cpp index af212d37f14..1773d3bc949 100644 --- a/src/xrpld/rpc/detail/Status.cpp +++ b/src/xrpld/rpc/detail/Status.cpp @@ -36,9 +36,8 @@ Status::codeString() const { std::string s1, s2; - auto success = transResultInfo(toTER(), s1, s2); - assert(success); - (void)success; + [[maybe_unused]] auto const success = transResultInfo(toTER(), s1, s2); + ASSERT(success, "ripple::RPC::codeString : valid TER result"); return s1 + ": " + s2; } @@ -51,7 +50,7 @@ Status::codeString() const return sStr.str(); } - assert(false); + UNREACHABLE("ripple::RPC::codeString : invalid type"); return ""; } diff --git a/src/xrpld/rpc/detail/TransactionSign.cpp b/src/xrpld/rpc/detail/TransactionSign.cpp index 2f10387bc81..3623b26d356 100644 --- a/src/xrpld/rpc/detail/TransactionSign.cpp +++ b/src/xrpld/rpc/detail/TransactionSign.cpp @@ -1031,7 +1031,9 @@ transactionSignFor( if (!preprocResult.second) return preprocResult.first; - assert(signForParams.validMultiSign()); + ASSERT( + signForParams.validMultiSign(), + "ripple::RPC::transactionSignFor : valid multi-signature"); { std::shared_ptr account_state = diff --git a/src/xrpld/rpc/handlers/AMMInfo.cpp b/src/xrpld/rpc/handlers/AMMInfo.cpp index 9d5b20f1d63..e6a1d713a4a 100644 --- a/src/xrpld/rpc/handlers/AMMInfo.cpp +++ b/src/xrpld/rpc/handlers/AMMInfo.cpp @@ -147,14 +147,17 @@ doAMMInfo(RPC::JsonContext& context) if (context.apiVersion >= 3 && invalid(params)) return Unexpected(rpcINVALID_PARAMS); - assert( + ASSERT( (issue1.has_value() == issue2.has_value()) && - (issue1.has_value() != ammID.has_value())); + (issue1.has_value() != ammID.has_value()), + "ripple::doAMMInfo : issue1 and issue2 do match"); auto const ammKeylet = [&]() { if (issue1 && issue2) return keylet::amm(*issue1, *issue2); - assert(ammID); + ASSERT( + ammID.has_value(), + "ripple::doAMMInfo::ammKeylet : ammID is set"); return keylet::amm(*ammID); }(); auto const amm = ledger->read(ammKeylet); @@ -213,9 +216,10 @@ doAMMInfo(RPC::JsonContext& context) } if (voteSlots.size() > 0) ammResult[jss::vote_slots] = std::move(voteSlots); - assert( + ASSERT( !ledger->rules().enabled(fixInnerObjTemplate) || - amm->isFieldPresent(sfAuctionSlot)); + amm->isFieldPresent(sfAuctionSlot), + "ripple::doAMMInfo : auction slot is set"); if (amm->isFieldPresent(sfAuctionSlot)) { auto const& auctionSlot = diff --git a/src/xrpld/rpc/handlers/AccountChannels.cpp b/src/xrpld/rpc/handlers/AccountChannels.cpp index ad591b04a1c..4b9ff7e43c5 100644 --- a/src/xrpld/rpc/handlers/AccountChannels.cpp +++ b/src/xrpld/rpc/handlers/AccountChannels.cpp @@ -169,7 +169,7 @@ doAccountChannels(RPC::JsonContext& context) std::shared_ptr const& sleCur) { if (!sleCur) { - assert(false); + UNREACHABLE("ripple::doAccountChannels : null SLE"); return false; } diff --git a/src/xrpld/rpc/handlers/AccountInfo.cpp b/src/xrpld/rpc/handlers/AccountInfo.cpp index dab0274e9dd..4f62eb5880a 100644 --- a/src/xrpld/rpc/handlers/AccountInfo.cpp +++ b/src/xrpld/rpc/handlers/AccountInfo.cpp @@ -214,7 +214,9 @@ doAccountInfo(RPC::JsonContext& context) if (tx.seqProxy.isSeq()) { - assert(prevSeqProxy < tx.seqProxy); + ASSERT( + prevSeqProxy < tx.seqProxy, + "rpple::doAccountInfo : first sorted proxy"); prevSeqProxy = tx.seqProxy; jvTx[jss::seq] = tx.seqProxy.value(); ++seqCount; @@ -224,7 +226,9 @@ doAccountInfo(RPC::JsonContext& context) } else { - assert(prevSeqProxy < tx.seqProxy); + ASSERT( + prevSeqProxy < tx.seqProxy, + "rpple::doAccountInfo : second sorted proxy"); prevSeqProxy = tx.seqProxy; jvTx[jss::ticket] = tx.seqProxy.value(); ++ticketCount; diff --git a/src/xrpld/rpc/handlers/AccountLines.cpp b/src/xrpld/rpc/handlers/AccountLines.cpp index 64ca95ebe56..e2e6ce19ded 100644 --- a/src/xrpld/rpc/handlers/AccountLines.cpp +++ b/src/xrpld/rpc/handlers/AccountLines.cpp @@ -189,7 +189,7 @@ doAccountLines(RPC::JsonContext& context) std::shared_ptr const& sleCur) { if (!sleCur) { - assert(false); + UNREACHABLE("ripple::doAccountLines : null SLE"); return false; } diff --git a/src/xrpld/rpc/handlers/AccountOffers.cpp b/src/xrpld/rpc/handlers/AccountOffers.cpp index 3c4a4404984..86559a79f4f 100644 --- a/src/xrpld/rpc/handlers/AccountOffers.cpp +++ b/src/xrpld/rpc/handlers/AccountOffers.cpp @@ -145,7 +145,7 @@ doAccountOffers(RPC::JsonContext& context) std::shared_ptr const& sle) { if (!sle) { - assert(false); + UNREACHABLE("ripple::doAccountOffers : null SLE"); return false; } diff --git a/src/xrpld/rpc/handlers/AccountTx.cpp b/src/xrpld/rpc/handlers/AccountTx.cpp index 887694daf21..5b391ebe3b6 100644 --- a/src/xrpld/rpc/handlers/AccountTx.cpp +++ b/src/xrpld/rpc/handlers/AccountTx.cpp @@ -307,7 +307,9 @@ populateJsonResponse( if (auto txnsData = std::get_if(&result.transactions)) { - assert(!args.binary); + ASSERT( + !args.binary, + "ripple::populateJsonResponse : binary is not set"); for (auto const& [txn, txnMeta] : *txnsData) { @@ -354,13 +356,15 @@ populateJsonResponse( jvObj[jss::meta], sttx, *txnMeta); } else - assert(false && "Missing transaction medatata"); + UNREACHABLE( + "ripple::populateJsonResponse : missing " + "transaction medatata"); } } } else { - assert(args.binary); + ASSERT(args.binary, "ripple::populateJsonResponse : binary is set"); for (auto const& binaryData : std::get(result.transactions)) diff --git a/src/xrpld/rpc/handlers/Fee1.cpp b/src/xrpld/rpc/handlers/Fee1.cpp index da766fdbb32..de5bdc4f6ca 100644 --- a/src/xrpld/rpc/handlers/Fee1.cpp +++ b/src/xrpld/rpc/handlers/Fee1.cpp @@ -32,7 +32,7 @@ doFee(RPC::JsonContext& context) auto result = context.app.getTxQ().doRPC(context.app); if (result.type() == Json::objectValue) return result; - assert(false); + UNREACHABLE("ripple::doFee : invalid result type"); RPC::inject_error(rpcINTERNAL, context.params); return context.params; } diff --git a/src/xrpld/rpc/handlers/LedgerClosed.cpp b/src/xrpld/rpc/handlers/LedgerClosed.cpp index 9bc9315f648..759f4aecd33 100644 --- a/src/xrpld/rpc/handlers/LedgerClosed.cpp +++ b/src/xrpld/rpc/handlers/LedgerClosed.cpp @@ -29,7 +29,8 @@ Json::Value doLedgerClosed(RPC::JsonContext& context) { auto ledger = context.ledgerMaster.getClosedLedger(); - assert(ledger); + ASSERT( + ledger != nullptr, "ripple::doLedgerClosed : non-null closed ledger"); Json::Value jvResult; jvResult[jss::ledger_index] = ledger->info().seq; diff --git a/src/xrpld/rpc/handlers/LedgerDiff.cpp b/src/xrpld/rpc/handlers/LedgerDiff.cpp index 6398be60973..e562197f4af 100644 --- a/src/xrpld/rpc/handlers/LedgerDiff.cpp +++ b/src/xrpld/rpc/handlers/LedgerDiff.cpp @@ -73,7 +73,9 @@ doLedgerDiffGrpc( } else { - assert(inDesired->size() > 0); + ASSERT( + inDesired->size() > 0, + "ripple::doLedgerDiffGrpc : non-empty desired"); diff->set_key(k.data(), k.size()); if (request.include_blobs()) { diff --git a/src/xrpld/rpc/handlers/LedgerHandler.cpp b/src/xrpld/rpc/handlers/LedgerHandler.cpp index 2bf4fb09f94..54f9a8b8459 100644 --- a/src/xrpld/rpc/handlers/LedgerHandler.cpp +++ b/src/xrpld/rpc/handlers/LedgerHandler.cpp @@ -135,7 +135,9 @@ doLedgerGrpc(RPC::GRPCContext& context) { for (auto& i : ledger->txs) { - assert(i.first); + ASSERT( + i.first != nullptr, + "ripple::doLedgerGrpc : non-null transaction"); if (request.expand()) { auto txn = response.mutable_transactions_list() @@ -211,7 +213,9 @@ doLedgerGrpc(RPC::GRPCContext& context) obj->set_key(k.data(), k.size()); if (inDesired) { - assert(inDesired->size() > 0); + ASSERT( + inDesired->size() > 0, + "ripple::doLedgerGrpc : non-empty desired"); obj->set_data(inDesired->data(), inDesired->size()); } if (inBase && inDesired) diff --git a/src/xrpld/rpc/handlers/PayChanClaim.cpp b/src/xrpld/rpc/handlers/PayChanClaim.cpp index 1fecd5f1449..e55191877ef 100644 --- a/src/xrpld/rpc/handlers/PayChanClaim.cpp +++ b/src/xrpld/rpc/handlers/PayChanClaim.cpp @@ -58,7 +58,9 @@ doChannelAuthorize(RPC::JsonContext& context) std::optional> const keyPair = RPC::keypairForSignature(params, result, context.apiVersion); - assert(keyPair || RPC::contains_error(result)); + ASSERT( + keyPair || RPC::contains_error(result), + "ripple::doChannelAuthorize : valid keyPair or an error"); if (!keyPair || RPC::contains_error(result)) return result; diff --git a/src/xrpld/rpc/handlers/Tx.cpp b/src/xrpld/rpc/handlers/Tx.cpp index 98af3a809bf..af08575bbd8 100644 --- a/src/xrpld/rpc/handlers/Tx.cpp +++ b/src/xrpld/rpc/handlers/Tx.cpp @@ -251,7 +251,7 @@ populateJsonResponse( // populate binary metadata if (auto blob = std::get_if(&result.meta)) { - assert(args.binary); + ASSERT(args.binary, "ripple::populateJsonResponse : binary is set"); auto json_meta = (context.apiVersion > 1 ? jss::meta_blob : jss::meta); response[json_meta] = strHex(makeSlice(*blob)); diff --git a/src/xrpld/shamap/SHAMap.h b/src/xrpld/shamap/SHAMap.h index a47f1c1c2bc..cc9a8d9e6ae 100644 --- a/src/xrpld/shamap/SHAMap.h +++ b/src/xrpld/shamap/SHAMap.h @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include #include @@ -599,7 +599,9 @@ SHAMap::setLedgerSeq(std::uint32_t lseq) inline void SHAMap::setImmutable() { - assert(state_ != SHAMapState::Invalid); + ASSERT( + state_ != SHAMapState::Invalid, + "ripple::SHAMap::setImmutable : state is valid"); state_ = SHAMapState::Immutable; } @@ -680,7 +682,9 @@ class SHAMap::const_iterator inline SHAMap::const_iterator::const_iterator(SHAMap const* map) : map_(map) { - assert(map_ != nullptr); + ASSERT( + map_ != nullptr, + "ripple::SHAMap::const_iterator::const_iterator : non-null input"); if (auto temp = map_->peekFirstItem(stack_)) item_ = temp->peekItem().get(); @@ -732,7 +736,10 @@ SHAMap::const_iterator::operator++(int) inline bool operator==(SHAMap::const_iterator const& x, SHAMap::const_iterator const& y) { - assert(x.map_ == y.map_); + ASSERT( + x.map_ == y.map_, + "ripple::operator==(SHAMap::const_iterator, SHAMap::const_iterator) : " + "inputs map do match"); return x.item_ == y.item_; } diff --git a/src/xrpld/shamap/SHAMapItem.h b/src/xrpld/shamap/SHAMapItem.h index 1a1822456e9..e49762a50b2 100644 --- a/src/xrpld/shamap/SHAMapItem.h +++ b/src/xrpld/shamap/SHAMapItem.h @@ -25,8 +25,8 @@ #include #include #include +#include #include -#include namespace ripple { @@ -159,7 +159,9 @@ intrusive_ptr_release(SHAMapItem const* x) inline boost::intrusive_ptr make_shamapitem(uint256 const& tag, Slice data) { - assert(data.size() <= megabytes(16)); + ASSERT( + data.size() <= megabytes(16), + "ripple::make_shamapitem : maximum input size"); std::uint8_t* raw = detail::slabber.allocate(data.size()); diff --git a/src/xrpld/shamap/detail/SHAMap.cpp b/src/xrpld/shamap/detail/SHAMap.cpp index d06ba2a153a..11cf079320f 100644 --- a/src/xrpld/shamap/detail/SHAMap.cpp +++ b/src/xrpld/shamap/detail/SHAMap.cpp @@ -101,10 +101,12 @@ SHAMap::dirtyUp( // stack is a path of inner nodes up to, but not including, child // child can be an inner node or a leaf - assert( - (state_ != SHAMapState::Synching) && - (state_ != SHAMapState::Immutable)); - assert(child && (child->cowid() == cowid_)); + ASSERT( + (state_ != SHAMapState::Synching) && (state_ != SHAMapState::Immutable), + "ripple::SHAMap::dirtyUp : valid state"); + ASSERT( + child && (child->cowid() == cowid_), + "ripple::SHAMap::dirtyUp : valid child input"); while (!stack.empty()) { @@ -112,10 +114,10 @@ SHAMap::dirtyUp( std::dynamic_pointer_cast(stack.top().first); SHAMapNodeID nodeID = stack.top().second; stack.pop(); - assert(node != nullptr); + ASSERT(node != nullptr, "ripple::SHAMap::dirtyUp : non-null node"); int branch = selectBranch(nodeID, target); - assert(branch >= 0); + ASSERT(branch >= 0, "ripple::SHAMap::dirtyUp : valid branch"); node = unshareNode(std::move(node), nodeID); node->setChild(branch, std::move(child)); @@ -127,7 +129,9 @@ SHAMap::dirtyUp( SHAMapLeafNode* SHAMap::walkTowardsKey(uint256 const& id, SharedPtrNodeStack* stack) const { - assert(stack == nullptr || stack->empty()); + ASSERT( + stack == nullptr || stack->empty(), + "ripple::SHAMap::walkTowardsKey : empty stack input"); auto inNode = root_; SHAMapNodeID nodeID; @@ -162,7 +166,7 @@ SHAMap::findKey(uint256 const& id) const std::shared_ptr SHAMap::fetchNodeFromDB(SHAMapHash const& hash) const { - assert(backed_); + ASSERT(backed_, "ripple::SHAMap::fetchNodeFromDB : is backed"); auto obj = f_.db().fetchNodeObject(hash.as_uint256(), ledgerSeq_); return finishFetch(hash, obj); } @@ -172,7 +176,7 @@ SHAMap::finishFetch( SHAMapHash const& hash, std::shared_ptr const& object) const { - assert(backed_); + ASSERT(backed_, "ripple::SHAMap::finishFetch : is backed"); try { @@ -360,9 +364,13 @@ SHAMap::descend( int branch, SHAMapSyncFilter* filter) const { - assert(parent->isInner()); - assert((branch >= 0) && (branch < branchFactor)); - assert(!parent->isEmptyBranch(branch)); + ASSERT(parent->isInner(), "ripple::SHAMap::descend : valid parent input"); + ASSERT( + (branch >= 0) && (branch < branchFactor), + "ripple::SHAMap::descend : valid branch input"); + ASSERT( + !parent->isEmptyBranch(branch), + "ripple::SHAMap::descend : parent branch is non-empty"); SHAMapTreeNode* child = parent->getChildPointer(branch); @@ -430,11 +438,15 @@ std::shared_ptr SHAMap::unshareNode(std::shared_ptr node, SHAMapNodeID const& nodeID) { // make sure the node is suitable for the intended operation (copy on write) - assert(node->cowid() <= cowid_); + ASSERT( + node->cowid() <= cowid_, + "ripple::SHAMap::unshareNode : node valid for cowid"); if (node->cowid() != cowid_) { // have a CoW - assert(state_ != SHAMapState::Immutable); + ASSERT( + state_ != SHAMapState::Immutable, + "ripple::SHAMap::unshareNode : not immutable"); node = std::static_pointer_cast(node->clone(cowid_)); if (nodeID.isRoot()) root_ = node; @@ -467,7 +479,9 @@ SHAMap::belowHelper( if (!inner->isEmptyBranch(i)) { node = descendThrow(inner, i); - assert(!stack.empty()); + ASSERT( + !stack.empty(), + "ripple::SHAMap::belowHelper : non-empty stack"); if (node->isLeaf()) { auto n = std::static_pointer_cast(node); @@ -531,7 +545,7 @@ SHAMap::onlyBelow(SHAMapTreeNode* node) const if (!nextNode) { - assert(false); + UNREACHABLE("ripple::SHAMap::onlyBelow : no next node"); return no_item; } @@ -541,14 +555,16 @@ SHAMap::onlyBelow(SHAMapTreeNode* node) const // An inner node must have at least one leaf // below it, unless it's the root_ auto const leaf = static_cast(node); - assert(leaf->peekItem() || (leaf == root_.get())); + ASSERT( + leaf->peekItem() || (leaf == root_.get()), + "ripple::SHAMap::onlyBelow : valid inner node"); return leaf->peekItem(); } SHAMapLeafNode const* SHAMap::peekFirstItem(SharedPtrNodeStack& stack) const { - assert(stack.empty()); + ASSERT(stack.empty(), "ripple::SHAMap::peekFirstItem : empty stack input"); SHAMapLeafNode* node = firstBelow(root_, stack); if (!node) { @@ -562,13 +578,18 @@ SHAMap::peekFirstItem(SharedPtrNodeStack& stack) const SHAMapLeafNode const* SHAMap::peekNextItem(uint256 const& id, SharedPtrNodeStack& stack) const { - assert(!stack.empty()); - assert(stack.top().first->isLeaf()); + ASSERT( + !stack.empty(), "ripple::SHAMap::peekNextItem : non-empty stack input"); + ASSERT( + stack.top().first->isLeaf(), + "ripple::SHAMap::peekNextItem : stack starts with leaf"); stack.pop(); while (!stack.empty()) { auto [node, nodeID] = stack.top(); - assert(!node->isLeaf()); + ASSERT( + !node->isLeaf(), + "ripple::SHAMap::peekNextItem : another node is not leaf"); auto inner = std::static_pointer_cast(node); for (auto i = selectBranch(nodeID, id) + 1; i < branchFactor; ++i) { @@ -578,7 +599,9 @@ SHAMap::peekNextItem(uint256 const& id, SharedPtrNodeStack& stack) const auto leaf = firstBelow(node, stack, i); if (!leaf) Throw(type_, id); - assert(leaf->isLeaf()); + ASSERT( + leaf->isLeaf(), + "ripple::SHAMap::peekNextItem : leaf is valid"); return leaf; } } @@ -696,7 +719,9 @@ bool SHAMap::delItem(uint256 const& id) { // delete the item with this ID - assert(state_ != SHAMapState::Immutable); + ASSERT( + state_ != SHAMapState::Immutable, + "ripple::SHAMap::delItem : not immutable"); SharedPtrNodeStack stack; walkTowardsKey(id, &stack); @@ -775,8 +800,12 @@ SHAMap::addGiveItem( SHAMapNodeType type, boost::intrusive_ptr item) { - assert(state_ != SHAMapState::Immutable); - assert(type != SHAMapNodeType::tnINNER); + ASSERT( + state_ != SHAMapState::Immutable, + "ripple::SHAMap::addGiveItem : not immutable"); + ASSERT( + type != SHAMapNodeType::tnINNER, + "ripple::SHAMap::addGiveItem : valid type input"); // add the specified item, does not update uint256 tag = item->key(); @@ -802,7 +831,9 @@ SHAMap::addGiveItem( // easy case, we end on an inner node auto inner = std::static_pointer_cast(node); int branch = selectBranch(nodeID, tag); - assert(inner->isEmptyBranch(branch)); + ASSERT( + inner->isEmptyBranch(branch), + "ripple::SHAMap::addGiveItem : inner branch is empty"); inner->setChild(branch, makeTypedLeaf(type, std::move(item), cowid_)); } else @@ -811,7 +842,9 @@ SHAMap::addGiveItem( // items auto leaf = std::static_pointer_cast(node); auto otherItem = leaf->peekItem(); - assert(otherItem && (tag != otherItem->key())); + ASSERT( + otherItem && (tag != otherItem->key()), + "ripple::SHAMap::addGiveItem : non-null item"); node = std::make_shared(node->cowid()); @@ -829,7 +862,7 @@ SHAMap::addGiveItem( } // we can add the two leaf nodes here - assert(node->isInner()); + ASSERT(node->isInner(), "ripple::SHAMap::addGiveItem : node is inner"); auto inner = static_cast(node.get()); inner->setChild(b1, makeTypedLeaf(type, std::move(item), cowid_)); @@ -868,7 +901,9 @@ SHAMap::updateGiveItem( // can't change the tag but can change the hash uint256 tag = item->key(); - assert(state_ != SHAMapState::Immutable); + ASSERT( + state_ != SHAMapState::Immutable, + "ripple::SHAMap::updateGiveItem : not immutable"); SharedPtrNodeStack stack; walkTowardsKey(tag, &stack); @@ -882,7 +917,7 @@ SHAMap::updateGiveItem( if (!node || (node->peekItem()->key() != tag)) { - assert(false); + UNREACHABLE("ripple::SHAMap::updateGiveItem : invalid node"); return false; } @@ -927,7 +962,9 @@ SHAMap::fetchRoot(SHAMapHash const& hash, SHAMapSyncFilter* filter) if (newRoot) { root_ = newRoot; - assert(root_->getHash() == hash); + ASSERT( + root_->getHash() == hash, + "ripple::SHAMap::fetchRoot : root hash do match"); return true; } @@ -949,8 +986,8 @@ SHAMap::fetchRoot(SHAMapHash const& hash, SHAMapSyncFilter* filter) std::shared_ptr SHAMap::writeNode(NodeObjectType t, std::shared_ptr node) const { - assert(node->cowid() == 0); - assert(backed_); + ASSERT(node->cowid() == 0, "ripple::SHAMap::writeNode : valid input node"); + ASSERT(backed_, "ripple::SHAMap::writeNode : is backed"); canonicalize(node->getHash(), node); @@ -970,7 +1007,8 @@ SHAMap::preFlushNode(std::shared_ptr node) const { // A shared node should never need to be flushed // because that would imply someone modified it - assert(node->cowid() != 0); + ASSERT( + node->cowid() != 0, "ripple::SHAMap::preFlushNode : valid input node"); if (node->cowid() != cowid_) { @@ -998,7 +1036,7 @@ SHAMap::flushDirty(NodeObjectType t) int SHAMap::walkSubTree(bool doWrite, NodeObjectType t) { - assert(!doWrite || backed_); + ASSERT(!doWrite || backed_, "ripple::SHAMap::walkSubTree : valid input"); int flushed = 0; @@ -1073,7 +1111,10 @@ SHAMap::walkSubTree(bool doWrite, NodeObjectType t) // flush this leaf ++flushed; - assert(node->cowid() == cowid_); + ASSERT( + node->cowid() == cowid_, + "ripple::SHAMap::walkSubTree : node cowid do " + "match"); child->updateHash(); child->unshare(); @@ -1106,7 +1147,9 @@ SHAMap::walkSubTree(bool doWrite, NodeObjectType t) stack.pop(); // Hook this inner node to its parent - assert(parent->cowid() == cowid_); + ASSERT( + parent->cowid() == cowid_, + "ripple::SHAMap::walkSubTree : parent cowid do match"); parent->shareChild(pos, node); // Continue with parent's next child, if any @@ -1150,7 +1193,9 @@ SHAMap::dump(bool hash) const auto child = inner->getChildPointer(i); if (child) { - assert(child->getHash() == inner->getChildHash(i)); + ASSERT( + child->getHash() == inner->getChildHash(i), + "ripple::SHAMap::dump : child hash do match"); stack.push({child, nodeID.getChildNodeID(i)}); } } @@ -1167,7 +1212,9 @@ std::shared_ptr SHAMap::cacheLookup(SHAMapHash const& hash) const { auto ret = f_.getTreeNodeCache()->fetch(hash.as_uint256()); - assert(!ret || !ret->cowid()); + ASSERT( + !ret || !ret->cowid(), + "ripple::SHAMap::cacheLookup : not found or zero cowid"); return ret; } @@ -1176,9 +1223,12 @@ SHAMap::canonicalize( SHAMapHash const& hash, std::shared_ptr& node) const { - assert(backed_); - assert(node->cowid() == 0); - assert(node->getHash() == hash); + ASSERT(backed_, "ripple::SHAMap::canonicalize : is backed"); + ASSERT( + node->cowid() == 0, "ripple::SHAMap::canonicalize : valid node input"); + ASSERT( + node->getHash() == hash, + "ripple::SHAMap::canonicalize : node hash do match"); f_.getTreeNodeCache()->canonicalize_replace_client(hash.as_uint256(), node); } @@ -1188,8 +1238,9 @@ SHAMap::invariants() const { (void)getHash(); // update node hashes auto node = root_.get(); - assert(node != nullptr); - assert(!node->isLeaf()); + ASSERT(node != nullptr, "ripple::SHAMap::invariants : non-null root node"); + ASSERT( + !node->isLeaf(), "ripple::SHAMap::invariants : root node is not leaf"); SharedPtrNodeStack stack; for (auto leaf = peekFirstItem(stack); leaf != nullptr; leaf = peekNextItem(leaf->peekItem()->key(), stack)) diff --git a/src/xrpld/shamap/detail/SHAMapDelta.cpp b/src/xrpld/shamap/detail/SHAMapDelta.cpp index 0dcb861a63f..b2f62685829 100644 --- a/src/xrpld/shamap/detail/SHAMapDelta.cpp +++ b/src/xrpld/shamap/detail/SHAMapDelta.cpp @@ -128,7 +128,9 @@ SHAMap::compare(SHAMap const& otherMap, Delta& differences, int maxCount) const // many differences throws on corrupt tables or missing nodes CAUTION: // otherMap is not locked and must be immutable - assert(isValid() && otherMap.isValid()); + ASSERT( + isValid() && otherMap.isValid(), + "ripple::SHAMap::compare : valid state and valid input"); if (getHash() == otherMap.getHash()) return true; @@ -145,7 +147,7 @@ SHAMap::compare(SHAMap const& otherMap, Delta& differences, int maxCount) const if (!ourNode || !otherNode) { - assert(false); + UNREACHABLE("ripple::SHAMap::compare : missing a node"); Throw(type_, uint256()); } @@ -226,7 +228,7 @@ SHAMap::compare(SHAMap const& otherMap, Delta& differences, int maxCount) const } } else - assert(false); + UNREACHABLE("ripple::SHAMap::compare : invalid node"); } return true; @@ -323,7 +325,9 @@ SHAMap::walkMapParallel( { std::shared_ptr node = std::move(nodeStack.top()); - assert(node); + ASSERT( + node != nullptr, + "ripple::SHAMap::walkMapParallel : non-null node"); nodeStack.pop(); for (int i = 0; i < 16; ++i) diff --git a/src/xrpld/shamap/detail/SHAMapInnerNode.cpp b/src/xrpld/shamap/detail/SHAMapInnerNode.cpp index 99155a6401f..2f8448d7edc 100644 --- a/src/xrpld/shamap/detail/SHAMapInnerNode.cpp +++ b/src/xrpld/shamap/detail/SHAMapInnerNode.cpp @@ -225,7 +225,8 @@ SHAMapInnerNode::updateHashDeep() void SHAMapInnerNode::serializeForWire(Serializer& s) const { - assert(!isEmpty()); + ASSERT( + !isEmpty(), "ripple::SHAMapInnerNode::serializeForWire : is non-empty"); // If the node is sparse, then only send non-empty branches: if (getBranchCount() < 12) @@ -249,7 +250,9 @@ SHAMapInnerNode::serializeForWire(Serializer& s) const void SHAMapInnerNode::serializeWithPrefix(Serializer& s) const { - assert(!isEmpty()); + ASSERT( + !isEmpty(), + "ripple::SHAMapInnerNode::serializeWithPrefix : is non-empty"); s.add32(HashPrefix::innerNode); iterChildren( @@ -274,9 +277,13 @@ SHAMapInnerNode::getString(const SHAMapNodeID& id) const void SHAMapInnerNode::setChild(int m, std::shared_ptr child) { - assert((m >= 0) && (m < branchFactor)); - assert(cowid_ != 0); - assert(child.get() != this); + ASSERT( + (m >= 0) && (m < branchFactor), + "ripple::SHAMapInnerNode::setChild : valid branch input"); + ASSERT(cowid_ != 0, "ripple::SHAMapInnerNode::setChild : nonzero cowid"); + ASSERT( + child.get() != this, + "ripple::SHAMapInnerNode::setChild : valid child input"); auto const dstIsBranch = [&] { if (child) @@ -303,27 +310,41 @@ SHAMapInnerNode::setChild(int m, std::shared_ptr child) hash_.zero(); - assert(getBranchCount() <= hashesAndChildren_.capacity()); + ASSERT( + getBranchCount() <= hashesAndChildren_.capacity(), + "ripple::SHAMapInnerNode::setChild : maximum branch count"); } // finished modifying, now make shareable void SHAMapInnerNode::shareChild(int m, std::shared_ptr const& child) { - assert((m >= 0) && (m < branchFactor)); - assert(cowid_ != 0); - assert(child); - assert(child.get() != this); - - assert(!isEmptyBranch(m)); + ASSERT( + (m >= 0) && (m < branchFactor), + "ripple::SHAMapInnerNode::shareChild : valid branch input"); + ASSERT(cowid_ != 0, "ripple::SHAMapInnerNode::shareChild : nonzero cowid"); + ASSERT( + child != nullptr, + "ripple::SHAMapInnerNode::shareChild : non-null child input"); + ASSERT( + child.get() != this, + "ripple::SHAMapInnerNode::shareChild : valid child input"); + + ASSERT( + !isEmptyBranch(m), + "ripple::SHAMapInnerNode::shareChild : non-empty branch input"); hashesAndChildren_.getChildren()[*getChildIndex(m)] = child; } SHAMapTreeNode* SHAMapInnerNode::getChildPointer(int branch) { - assert(branch >= 0 && branch < branchFactor); - assert(!isEmptyBranch(branch)); + ASSERT( + branch >= 0 && branch < branchFactor, + "ripple::SHAMapInnerNode::getChildPointer : valid branch input"); + ASSERT( + !isEmptyBranch(branch), + "ripple::SHAMapInnerNode::getChildPointer : non-empty branch input"); auto const index = *getChildIndex(branch); @@ -335,8 +356,12 @@ SHAMapInnerNode::getChildPointer(int branch) std::shared_ptr SHAMapInnerNode::getChild(int branch) { - assert(branch >= 0 && branch < branchFactor); - assert(!isEmptyBranch(branch)); + ASSERT( + branch >= 0 && branch < branchFactor, + "ripple::SHAMapInnerNode::getChild : valid branch input"); + ASSERT( + !isEmptyBranch(branch), + "ripple::SHAMapInnerNode::getChild : non-empty branch input"); auto const index = *getChildIndex(branch); @@ -348,7 +373,9 @@ SHAMapInnerNode::getChild(int branch) SHAMapHash const& SHAMapInnerNode::getChildHash(int m) const { - assert((m >= 0) && (m < branchFactor)); + ASSERT( + (m >= 0) && (m < branchFactor), + "ripple::SHAMapInnerNode::getChildHash : valid branch input"); if (auto const i = getChildIndex(m)) return hashesAndChildren_.getHashes()[*i]; @@ -360,12 +387,21 @@ SHAMapInnerNode::canonicalizeChild( int branch, std::shared_ptr node) { - assert(branch >= 0 && branch < branchFactor); - assert(node); - assert(!isEmptyBranch(branch)); + ASSERT( + branch >= 0 && branch < branchFactor, + "ripple::SHAMapInnerNode::canonicalizeChild : valid branch input"); + ASSERT( + node != nullptr, + "ripple::SHAMapInnerNode::canonicalizeChild : valid node input"); + ASSERT( + !isEmptyBranch(branch), + "ripple::SHAMapInnerNode::canonicalizeChild : non-empty branch input"); auto const childIndex = *getChildIndex(branch); auto [_, hashes, children] = hashesAndChildren_.getHashesAndChildren(); - assert(node->getHash() == hashes[childIndex]); + ASSERT( + node->getHash() == hashes[childIndex], + "ripple::SHAMapInnerNode::canonicalizeChild : node and branch inputs " + "hash do match"); packed_spinlock sl(lock_, childIndex); std::lock_guard lock(sl); @@ -395,7 +431,9 @@ SHAMapInnerNode::invariants(bool is_root) const auto const branchCount = getBranchCount(); for (int i = 0; i < branchCount; ++i) { - assert(hashes[i].isNonZero()); + ASSERT( + hashes[i].isNonZero(), + "ripple::SHAMapInnerNode::invariants : nonzero hash in branch"); if (children[i] != nullptr) children[i]->invariants(); ++count; @@ -407,24 +445,35 @@ SHAMapInnerNode::invariants(bool is_root) const { if (hashes[i].isNonZero()) { - assert((isBranch_ & (1 << i)) != 0); + ASSERT( + (isBranch_ & (1 << i)) != 0, + "ripple::SHAMapInnerNode::invariants : valid branch when " + "nonzero hash"); if (children[i] != nullptr) children[i]->invariants(); ++count; } else { - assert((isBranch_ & (1 << i)) == 0); + ASSERT( + (isBranch_ & (1 << i)) == 0, + "ripple::SHAMapInnerNode::invariants : valid branch when " + "zero hash"); } } } if (!is_root) { - assert(hash_.isNonZero()); - assert(count >= 1); + ASSERT( + hash_.isNonZero(), + "ripple::SHAMapInnerNode::invariants : nonzero hash"); + ASSERT( + count >= 1, "ripple::SHAMapInnerNode::invariants : minimum count"); } - assert((count == 0) ? hash_.isZero() : hash_.isNonZero()); + ASSERT( + (count == 0) ? hash_.isZero() : hash_.isNonZero(), + "ripple::SHAMapInnerNode::invariants : hash and count do match"); } } // namespace ripple diff --git a/src/xrpld/shamap/detail/SHAMapLeafNode.cpp b/src/xrpld/shamap/detail/SHAMapLeafNode.cpp index 972919a9bda..f6f13cfdaab 100644 --- a/src/xrpld/shamap/detail/SHAMapLeafNode.cpp +++ b/src/xrpld/shamap/detail/SHAMapLeafNode.cpp @@ -28,7 +28,10 @@ SHAMapLeafNode::SHAMapLeafNode( std::uint32_t cowid) : SHAMapTreeNode(cowid), item_(std::move(item)) { - assert(item_->size() >= 12); + ASSERT( + item_->size() >= 12, + "ripple::SHAMapLeafNode::SHAMapLeafNode(boost::intrusive_ptr<" + "SHAMapItem const>, std::uint32_t) : minimum input size"); } SHAMapLeafNode::SHAMapLeafNode( @@ -37,7 +40,11 @@ SHAMapLeafNode::SHAMapLeafNode( SHAMapHash const& hash) : SHAMapTreeNode(cowid, hash), item_(std::move(item)) { - assert(item_->size() >= 12); + ASSERT( + item_->size() >= 12, + "ripple::SHAMapLeafNode::SHAMapLeafNode(boost::intrusive_ptr<" + "SHAMapItem const>, std::uint32_t, SHAMapHash const&) : minimum input " + "size"); } boost::intrusive_ptr const& @@ -49,7 +56,7 @@ SHAMapLeafNode::peekItem() const bool SHAMapLeafNode::setItem(boost::intrusive_ptr item) { - assert(cowid_ != 0); + ASSERT(cowid_ != 0, "ripple::SHAMapLeafNode::setItem : nonzero cowid"); item_ = std::move(item); auto const oldHash = hash_; @@ -87,8 +94,10 @@ SHAMapLeafNode::getString(const SHAMapNodeID& id) const void SHAMapLeafNode::invariants(bool) const { - assert(hash_.isNonZero()); - assert(item_ != nullptr); + ASSERT( + hash_.isNonZero(), "ripple::SHAMapLeafNode::invariants : nonzero hash"); + ASSERT( + item_ != nullptr, "ripple::SHAMapLeafNode::invariants : non-null item"); } } // namespace ripple diff --git a/src/xrpld/shamap/detail/SHAMapNodeID.cpp b/src/xrpld/shamap/detail/SHAMapNodeID.cpp index 5cbd095e7a9..82cf9436366 100644 --- a/src/xrpld/shamap/detail/SHAMapNodeID.cpp +++ b/src/xrpld/shamap/detail/SHAMapNodeID.cpp @@ -20,9 +20,9 @@ #include #include #include +#include #include #include -#include namespace ripple { @@ -57,8 +57,12 @@ depthMask(unsigned int depth) SHAMapNodeID::SHAMapNodeID(unsigned int depth, uint256 const& hash) : id_(hash), depth_(depth) { - assert(depth <= SHAMap::leafDepth); - assert(id_ == (id_ & depthMask(depth))); + ASSERT( + depth <= SHAMap::leafDepth, + "ripple::SHAMapNodeID::SHAMapNodeID : maximum depth input"); + ASSERT( + id_ == (id_ & depthMask(depth)), + "ripple::SHAMapNodeID::SHAMapNodeID : hash and depth inputs do match"); } std::string @@ -73,7 +77,9 @@ SHAMapNodeID::getRawString() const SHAMapNodeID SHAMapNodeID::getChildNodeID(unsigned int m) const { - assert(m < SHAMap::branchFactor); + ASSERT( + m < SHAMap::branchFactor, + "ripple::SHAMapNodeID::getChildNodeID : valid branch input"); // A SHAMap has exactly 65 levels, so nodes must not exceed that // depth; if they do, this breaks the invariant of never allowing @@ -83,7 +89,9 @@ SHAMapNodeID::getChildNodeID(unsigned int m) const // We throw (but never assert) if the node is at level 64, since // entries at that depth are leaf nodes and have no children and even // constructing a child node from them would break the above invariant. - assert(depth_ <= SHAMap::leafDepth); + ASSERT( + depth_ <= SHAMap::leafDepth, + "ripple::SHAMapNodeID::getChildNodeID : maximum leaf depth"); if (depth_ >= SHAMap::leafDepth) Throw( @@ -128,14 +136,17 @@ selectBranch(SHAMapNodeID const& id, uint256 const& hash) else branch >>= 4; - assert(branch < SHAMap::branchFactor); + ASSERT( + branch < SHAMap::branchFactor, "ripple::selectBranch : maximum result"); return branch; } SHAMapNodeID SHAMapNodeID::createID(int depth, uint256 const& key) { - assert((depth >= 0) && (depth < 65)); + ASSERT( + (depth >= 0) && (depth < 65), + "ripple::SHAMapNodeID::createID : valid branch input"); return SHAMapNodeID(depth, key & depthMask(depth)); } diff --git a/src/xrpld/shamap/detail/SHAMapSync.cpp b/src/xrpld/shamap/detail/SHAMapSync.cpp index 7235e526560..4425662415e 100644 --- a/src/xrpld/shamap/detail/SHAMapSync.cpp +++ b/src/xrpld/shamap/detail/SHAMapSync.cpp @@ -314,8 +314,10 @@ SHAMap::gmn_ProcessDeferredReads(MissingNodes& mn) std::vector> SHAMap::getMissingNodes(int max, SHAMapSyncFilter* filter) { - assert(root_->getHash().isNonZero()); - assert(max > 0); + ASSERT( + root_->getHash().isNonZero(), + "ripple::SHAMap::getMissingNodes : nonzero root hash"); + ASSERT(max > 0, "ripple::SHAMap::getMissingNodes : valid max input"); MissingNodes mn( max, @@ -374,7 +376,9 @@ SHAMap::getMissingNodes(int max, SHAMapSyncFilter* filter) // This is a node we are continuing to process fullBelow = fullBelow && was; // was and still is } - assert(node); + ASSERT( + node != nullptr, + "ripple::SHAMap::getMissingNodes : first non-null node"); } } @@ -405,7 +409,9 @@ SHAMap::getMissingNodes(int max, SHAMapSyncFilter* filter) // Resume at the top of the stack pos = mn.stack_.top(); mn.stack_.pop(); - assert(node != nullptr); + ASSERT( + node != nullptr, + "ripple::SHAMap::getMissingNodes : second non-null node"); } } @@ -532,11 +538,13 @@ SHAMap::addRootNode( if (root_->getHash().isNonZero()) { JLOG(journal_.trace()) << "got root node, already have one"; - assert(root_->getHash() == hash); + ASSERT( + root_->getHash() == hash, + "ripple::SHAMap::addRootNode : valid hash input"); return SHAMapAddNode::duplicate(); } - assert(cowid_ >= 1); + ASSERT(cowid_ >= 1, "ripple::SHAMap::addRootNode : valid cowid"); auto node = SHAMapTreeNode::makeFromWire(rootNode); if (!node || node->getHash() != hash) return SHAMapAddNode::invalid(); @@ -570,7 +578,7 @@ SHAMap::addKnownNode( Slice const& rawNode, SHAMapSyncFilter* filter) { - assert(!node.isRoot()); + ASSERT(!node.isRoot(), "ripple::SHAMap::addKnownNode : valid node input"); if (!isSynching()) { @@ -587,7 +595,7 @@ SHAMap::addKnownNode( (iNodeID.getDepth() < node.getDepth())) { int branch = selectBranch(iNodeID, node.getNodeID()); - assert(branch >= 0); + ASSERT(branch >= 0, "ripple::SHAMap::addKnownNode : valid branch"); auto inner = static_cast(iNode); if (inner->isEmptyBranch(branch)) { diff --git a/src/xrpld/shamap/detail/TaggedPointer.ipp b/src/xrpld/shamap/detail/TaggedPointer.ipp index 487b88e3461..3833ce58a11 100644 --- a/src/xrpld/shamap/detail/TaggedPointer.ipp +++ b/src/xrpld/shamap/detail/TaggedPointer.ipp @@ -79,14 +79,18 @@ constexpr auto chunksPerBlock = [[nodiscard]] inline std::uint8_t numAllocatedChildren(std::uint8_t n) { - assert(n <= SHAMapInnerNode::branchFactor); + ASSERT( + n <= SHAMapInnerNode::branchFactor, + "ripple::numAllocatedChildren : valid input"); return *std::lower_bound(boundaries.begin(), boundaries.end(), n); } [[nodiscard]] inline std::size_t boundariesIndex(std::uint8_t numChildren) { - assert(numChildren <= SHAMapInnerNode::branchFactor); + ASSERT( + numChildren <= SHAMapInnerNode::branchFactor, + "ripple::boundariesIndex : valid input"); return std::distance( boundaries.begin(), std::lower_bound(boundaries.begin(), boundaries.end(), numChildren)); @@ -156,7 +160,9 @@ allocateArrays(std::uint8_t numChildren) inline void deallocateArrays(std::uint8_t boundaryIndex, void* p) { - assert(isFromArrayFuns[boundaryIndex](p)); + ASSERT( + isFromArrayFuns[boundaryIndex](p), + "ripple::deallocateArrays : valid inputs"); freeArrayFuns[boundaryIndex](p); } @@ -270,10 +276,15 @@ TaggedPointer::getChildIndex(std::uint16_t isBranch, int i) const inline TaggedPointer::TaggedPointer(RawAllocateTag, std::uint8_t numChildren) { auto [tag, p] = allocateArrays(numChildren); - assert(tag < boundaries.size()); - assert( + ASSERT( + tag < boundaries.size(), + "ripple::TaggedPointer::TaggedPointer(RawAllocateTag, std::uint8_t) : " + "maximum tag"); + ASSERT( (reinterpret_cast(p) & ptrMask) == - reinterpret_cast(p)); + reinterpret_cast(p), + "ripple::TaggedPointer::TaggedPointer(RawAllocateTag, std::uint8_t) : " + "valid pointer"); tp_ = reinterpret_cast(p) + tag; } @@ -283,7 +294,10 @@ inline TaggedPointer::TaggedPointer( std::uint16_t dstBranches, std::uint8_t toAllocate) { - assert(toAllocate >= popcnt16(dstBranches)); + ASSERT( + toAllocate >= popcnt16(dstBranches), + "ripple::TaggedPointer::TaggedPointer(TaggedPointer&& ...) : minimum " + "toAllocate input"); if (other.capacity() == numAllocatedChildren(toAllocate)) { @@ -428,7 +442,10 @@ inline TaggedPointer::TaggedPointer( } } // If sparse, may need to run additional constructors - assert(!dstIsDense || dstIndex == dstNumAllocated); + ASSERT( + !dstIsDense || dstIndex == dstNumAllocated, + "ripple::TaggedPointer::TaggedPointer(TaggedPointer&& ...) : " + "non-sparse or valid sparse"); for (int i = dstIndex; i < dstNumAllocated; ++i) { new (&dstHashes[i]) SHAMapHash{};