mirror of
https://github.com/XRPLF/rippled.git
synced 2026-06-04 17:27:00 +00:00
Merge branch 'develop' into tapanito/unit-tests
This commit is contained in:
22
.clang-tidy
22
.clang-tidy
@@ -156,7 +156,13 @@ Checks: "-*,
|
||||
# readability-inconsistent-declaration-parameter-name, # in this codebase this check will break a lot of arg names
|
||||
# readability-static-accessed-through-instance, # this check is probably unnecessary. it makes the code less readable
|
||||
# ---
|
||||
|
||||
CheckOptions:
|
||||
bugprone-unsafe-functions.ReportMoreUnsafeFunctions: true
|
||||
bugprone-unused-return-value.CheckedReturnTypes: ::std::error_code;::std::error_condition;::std::errc
|
||||
|
||||
misc-include-cleaner.IgnoreHeaders: ".*/(detail|impl)/.*;.*fwd\\.h(pp)?;time.h;stdlib.h;sqlite3.h;netinet/in\\.h;sys/resource\\.h;sys/sysinfo\\.h;linux/sysinfo\\.h;__chrono/.*;bits/.*;_abort\\.h;boost/uuid/uuid_hash.hpp;boost/beast/core/flat_buffer\\.hpp;boost/beast/http/field\\.hpp;boost/beast/http/dynamic_body\\.hpp;boost/beast/http/message\\.hpp;boost/beast/http/read\\.hpp;boost/beast/http/write\\.hpp;openssl/obj_mac\\.h"
|
||||
|
||||
readability-braces-around-statements.ShortStatementLines: 2
|
||||
readability-identifier-naming.MacroDefinitionCase: UPPER_CASE
|
||||
readability-identifier-naming.ClassCase: CamelCase
|
||||
@@ -165,7 +171,7 @@ CheckOptions:
|
||||
readability-identifier-naming.EnumCase: CamelCase
|
||||
readability-identifier-naming.EnumConstantCase: CamelCase
|
||||
readability-identifier-naming.ScopedEnumConstantCase: CamelCase
|
||||
readability-identifier-naming.GlobalConstantCase: UPPER_CASE
|
||||
readability-identifier-naming.GlobalConstantCase: CamelCase
|
||||
readability-identifier-naming.GlobalConstantPrefix: "k"
|
||||
readability-identifier-naming.GlobalVariableCase: CamelCase
|
||||
readability-identifier-naming.GlobalVariablePrefix: "g"
|
||||
@@ -173,14 +179,12 @@ CheckOptions:
|
||||
readability-identifier-naming.ConstexprMethodCase: camelBack
|
||||
readability-identifier-naming.ClassMethodCase: camelBack
|
||||
readability-identifier-naming.ClassMemberCase: camelBack
|
||||
readability-identifier-naming.ClassConstantCase: UPPER_CASE
|
||||
readability-identifier-naming.ClassConstantCase: CamelCase
|
||||
readability-identifier-naming.ClassConstantPrefix: "k"
|
||||
readability-identifier-naming.StaticConstantCase: UPPER_CASE
|
||||
readability-identifier-naming.StaticConstantCase: CamelCase
|
||||
readability-identifier-naming.StaticConstantPrefix: "k"
|
||||
readability-identifier-naming.StaticVariableCase: UPPER_CASE
|
||||
readability-identifier-naming.StaticVariablePrefix: "k"
|
||||
readability-identifier-naming.ConstexprVariableCase: UPPER_CASE
|
||||
readability-identifier-naming.ConstexprVariablePrefix: "k"
|
||||
readability-identifier-naming.StaticVariableCase: camelBack
|
||||
readability-identifier-naming.ConstexprVariableCase: camelBack
|
||||
readability-identifier-naming.LocalConstantCase: camelBack
|
||||
readability-identifier-naming.LocalVariableCase: camelBack
|
||||
readability-identifier-naming.TemplateParameterCase: CamelCase
|
||||
@@ -191,9 +195,7 @@ CheckOptions:
|
||||
readability-identifier-naming.ProtectedMemberSuffix: _
|
||||
readability-identifier-naming.PublicMemberSuffix: ""
|
||||
readability-identifier-naming.GlobalFunctionIgnoredRegexp: "^(to_string|hash_append|tuple_hash)$"
|
||||
bugprone-unsafe-functions.ReportMoreUnsafeFunctions: true
|
||||
bugprone-unused-return-value.CheckedReturnTypes: ::std::error_code;::std::error_condition;::std::errc
|
||||
misc-include-cleaner.IgnoreHeaders: ".*/(detail|impl)/.*;.*fwd\\.h(pp)?;time.h;stdlib.h;sqlite3.h;netinet/in\\.h;sys/resource\\.h;sys/sysinfo\\.h;linux/sysinfo\\.h;__chrono/.*;bits/.*;_abort\\.h;boost/uuid/uuid_hash.hpp;boost/beast/core/flat_buffer\\.hpp;boost/beast/http/field\\.hpp;boost/beast/http/dynamic_body\\.hpp;boost/beast/http/message\\.hpp;boost/beast/http/read\\.hpp;boost/beast/http/write\\.hpp;openssl/obj_mac\\.h"
|
||||
|
||||
HeaderFilterRegex: '^.*/(test|xrpl|xrpld)/.*\.(h|hpp|ipp)$'
|
||||
ExcludeHeaderFilterRegex: '^.*/protocol_autogen/.*\.(h|hpp)$'
|
||||
WarningsAsErrors: "*"
|
||||
|
||||
2
.github/scripts/rename/config.sh
vendored
2
.github/scripts/rename/config.sh
vendored
@@ -62,7 +62,7 @@ ${SED_COMMAND} -i 's@ripple/@xrpld/@g' src/test/core/Config_test.cpp
|
||||
${SED_COMMAND} -i 's/Rippled/File/g' src/test/core/Config_test.cpp
|
||||
|
||||
# Restore the old config file name in the code that maintains support for now.
|
||||
${SED_COMMAND} -i 's/kCONFIG_LEGACY_NAME = "xrpld.cfg"/kCONFIG_LEGACY_NAME = "rippled.cfg"/g' src/xrpld/core/detail/Config.cpp
|
||||
${SED_COMMAND} -i 's/kConfigLegacyName = "xrpld.cfg"/kConfigLegacyName = "rippled.cfg"/g' src/xrpld/core/detail/Config.cpp
|
||||
|
||||
# Restore an URL.
|
||||
${SED_COMMAND} -i 's/connect-your-xrpld-to-the-xrp-test-net.html/connect-your-rippled-to-the-xrp-test-net.html/g' cfg/xrpld-example.cfg
|
||||
|
||||
2
.github/scripts/rename/docs.sh
vendored
2
.github/scripts/rename/docs.sh
vendored
@@ -90,7 +90,7 @@ ${SED_COMMAND} -i 's/www.ripple.com/www.xrpl.org/g' src/test/protocol/Seed_test.
|
||||
# Restore specific changes.
|
||||
${SED_COMMAND} -i 's@b5efcc/src/xrpld@b5efcc/src/ripple@' include/xrpl/protocol/README.md
|
||||
${SED_COMMAND} -i 's/dbPrefix_ = "xrpldb"/dbPrefix_ = "rippledb"/' src/xrpld/app/misc/SHAMapStoreImp.h # cspell: disable-line
|
||||
${SED_COMMAND} -i 's/kCONFIG_LEGACY_NAME = "xrpld.cfg"/kCONFIG_LEGACY_NAME = "rippled.cfg"/' src/xrpld/core/detail/Config.cpp
|
||||
${SED_COMMAND} -i 's/kConfigLegacyName = "xrpld.cfg"/kConfigLegacyName = "rippled.cfg"/' src/xrpld/core/detail/Config.cpp
|
||||
|
||||
popd
|
||||
echo "Renaming complete."
|
||||
|
||||
90
.github/scripts/strategy-matrix/generate.py
vendored
90
.github/scripts/strategy-matrix/generate.py
vendored
@@ -32,7 +32,32 @@ We will further set additional CMake arguments as follows:
|
||||
"""
|
||||
|
||||
|
||||
def generate_strategy_matrix(all: bool, config: Config) -> list:
|
||||
def build_config_name(os_entry: dict[str, str], platform: str, build_type: str) -> str:
|
||||
parts = [os_entry["distro_name"]]
|
||||
for key in ("distro_version", "compiler_name", "compiler_version"):
|
||||
if value := os_entry[key]:
|
||||
parts.append(value)
|
||||
parts.append("arm64" if "arm64" in platform else "amd64")
|
||||
parts.append(build_type.lower())
|
||||
return "-".join(parts)
|
||||
|
||||
|
||||
def generate_packaging_matrix(config: Config) -> list[dict]:
|
||||
"""Emit one entry per os entry with `package: true`. Architecture is
|
||||
hardcoded to linux/amd64 here (and the runner is hardcoded at the
|
||||
workflow level) until arm64 packaging is ready.
|
||||
"""
|
||||
return [
|
||||
{
|
||||
"artifact_name": f"xrpld-{build_config_name(os, 'linux/amd64', 'Release')}",
|
||||
"os": os,
|
||||
}
|
||||
for os in config.os
|
||||
if os.get("package", False)
|
||||
]
|
||||
|
||||
|
||||
def generate_strategy_matrix(all: bool, config: Config) -> list[dict]:
|
||||
configurations = []
|
||||
for architecture, os, build_type, cmake_args in itertools.product(
|
||||
config.architecture, config.os, config.build_type, config.cmake_args
|
||||
@@ -72,7 +97,7 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
|
||||
skip = False
|
||||
if (
|
||||
f"{os['compiler_name']}-{os['compiler_version']}" == "gcc-15"
|
||||
and build_type == "Debug"
|
||||
and build_type == "Release"
|
||||
and architecture["platform"] == "linux/amd64"
|
||||
):
|
||||
skip = False
|
||||
@@ -90,8 +115,9 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
|
||||
):
|
||||
cmake_args = f"-DUNIT_TEST_REFERENCE_FEE=1000 {cmake_args}"
|
||||
skip = False
|
||||
elif os["distro_version"] == "trixie":
|
||||
if (
|
||||
f"{os['compiler_name']}-{os['compiler_version']}" == "clang-20"
|
||||
f"{os['compiler_name']}-{os['compiler_version']}" == "clang-22"
|
||||
and build_type == "Debug"
|
||||
and architecture["platform"] == "linux/amd64"
|
||||
):
|
||||
@@ -100,14 +126,15 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
|
||||
continue
|
||||
|
||||
# RHEL:
|
||||
# - 9 using GCC 12: Debug on linux/amd64.
|
||||
# - 9 using GCC 12: Debug and Release on linux/amd64
|
||||
# (Release is required for RPM packaging).
|
||||
# - 10 using Clang: Release on linux/amd64.
|
||||
if os["distro_name"] == "rhel":
|
||||
skip = True
|
||||
if os["distro_version"] == "9":
|
||||
if (
|
||||
f"{os['compiler_name']}-{os['compiler_version']}" == "gcc-12"
|
||||
and build_type == "Debug"
|
||||
and build_type in ["Debug", "Release"]
|
||||
and architecture["platform"] == "linux/amd64"
|
||||
):
|
||||
skip = False
|
||||
@@ -122,7 +149,8 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
|
||||
continue
|
||||
|
||||
# Ubuntu:
|
||||
# - Jammy using GCC 12: Debug on linux/arm64.
|
||||
# - Jammy using GCC 12: Debug on linux/arm64, Release on
|
||||
# linux/amd64 (Release is required for DEB packaging).
|
||||
# - Noble using GCC 14: Release on linux/amd64.
|
||||
# - Noble using Clang 18: Debug on linux/amd64.
|
||||
# - Noble using Clang 19: Release on linux/arm64.
|
||||
@@ -135,6 +163,12 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
|
||||
and architecture["platform"] == "linux/arm64"
|
||||
):
|
||||
skip = False
|
||||
if (
|
||||
f"{os['compiler_name']}-{os['compiler_version']}" == "gcc-12"
|
||||
and build_type == "Release"
|
||||
and architecture["platform"] == "linux/amd64"
|
||||
):
|
||||
skip = False
|
||||
elif os["distro_version"] == "noble":
|
||||
if (
|
||||
f"{os['compiler_name']}-{os['compiler_version']}" == "gcc-14"
|
||||
@@ -188,8 +222,9 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
|
||||
|
||||
# We skip all clang 20+ on arm64 due to Boost build error.
|
||||
if (
|
||||
f"{os['compiler_name']}-{os['compiler_version']}"
|
||||
in ["clang-20", "clang-21"]
|
||||
os["compiler_name"] == "clang"
|
||||
and os["compiler_version"].isdigit()
|
||||
and int(os["compiler_version"]) >= 20
|
||||
and architecture["platform"] == "linux/arm64"
|
||||
):
|
||||
continue
|
||||
@@ -216,17 +251,7 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
|
||||
|
||||
# Generate a unique name for the configuration, e.g. macos-arm64-debug
|
||||
# or debian-bookworm-gcc-12-amd64-release.
|
||||
config_name = os["distro_name"]
|
||||
if (n := os["distro_version"]) != "":
|
||||
config_name += f"-{n}"
|
||||
if (n := os["compiler_name"]) != "":
|
||||
config_name += f"-{n}"
|
||||
if (n := os["compiler_version"]) != "":
|
||||
config_name += f"-{n}"
|
||||
config_name += (
|
||||
f"-{architecture['platform'][architecture['platform'].find('/')+1:]}"
|
||||
)
|
||||
config_name += f"-{build_type.lower()}"
|
||||
config_name = build_config_name(os, architecture["platform"], build_type)
|
||||
if "-Dcoverage=ON" in cmake_args:
|
||||
config_name += "-coverage"
|
||||
if "-Dunity=ON" in cmake_args:
|
||||
@@ -238,13 +263,14 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
|
||||
# Add Address and UB sanitizers as separate configurations for specific
|
||||
# bookworm distros. Thread sanitizer is currently disabled (see below).
|
||||
# GCC-Asan xrpld-embedded tests are failing because of https://github.com/google/sanitizers/issues/856
|
||||
if os[
|
||||
"distro_version"
|
||||
] == "bookworm" and f"{os['compiler_name']}-{os['compiler_version']}" in [
|
||||
"gcc-15",
|
||||
"clang-20",
|
||||
]:
|
||||
# Add ASAN configuration.
|
||||
if (
|
||||
os["distro_version"] == "bookworm"
|
||||
and f"{os['compiler_name']}-{os['compiler_version']}" == "gcc-15"
|
||||
) or (
|
||||
os["distro_version"] == "trixie"
|
||||
and f"{os['compiler_name']}-{os['compiler_version']}" == "clang-22"
|
||||
):
|
||||
# Add ASAN and UBSAN configurations for both gcc-15 and clang-22
|
||||
configurations.append(
|
||||
{
|
||||
"config_name": config_name + "-asan",
|
||||
@@ -257,7 +283,6 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
|
||||
"sanitizers": "address",
|
||||
}
|
||||
)
|
||||
# Add UBSAN configuration.
|
||||
configurations.append(
|
||||
{
|
||||
"config_name": config_name + "-ubsan",
|
||||
@@ -330,10 +355,19 @@ if __name__ == "__main__":
|
||||
required=False,
|
||||
type=Path,
|
||||
)
|
||||
parser.add_argument(
|
||||
"-p",
|
||||
"--packaging",
|
||||
help="Emit the packaging matrix (derived from the 'package' field on os entries) instead of the build/test matrix.",
|
||||
action="store_true",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
matrix = []
|
||||
if args.config is None or args.config == "":
|
||||
if args.packaging:
|
||||
config_path = args.config if args.config else THIS_DIR / "linux.json"
|
||||
matrix += generate_packaging_matrix(read_config(config_path))
|
||||
elif args.config is None or args.config == "":
|
||||
matrix += generate_strategy_matrix(
|
||||
args.all, read_config(THIS_DIR / "linux.json")
|
||||
)
|
||||
|
||||
65
.github/scripts/strategy-matrix/linux.json
vendored
65
.github/scripts/strategy-matrix/linux.json
vendored
@@ -15,196 +15,205 @@
|
||||
"distro_version": "bookworm",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "12",
|
||||
"image_sha": "ab4d1f0"
|
||||
"image_sha": "4c086b9"
|
||||
},
|
||||
{
|
||||
"distro_name": "debian",
|
||||
"distro_version": "bookworm",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "13",
|
||||
"image_sha": "ab4d1f0"
|
||||
"image_sha": "4c086b9"
|
||||
},
|
||||
{
|
||||
"distro_name": "debian",
|
||||
"distro_version": "bookworm",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "14",
|
||||
"image_sha": "ab4d1f0"
|
||||
"image_sha": "4c086b9"
|
||||
},
|
||||
{
|
||||
"distro_name": "debian",
|
||||
"distro_version": "bookworm",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "15",
|
||||
"image_sha": "ab4d1f0"
|
||||
"image_sha": "4c086b9"
|
||||
},
|
||||
{
|
||||
"distro_name": "debian",
|
||||
"distro_version": "bookworm",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "16",
|
||||
"image_sha": "ab4d1f0"
|
||||
"image_sha": "4c086b9"
|
||||
},
|
||||
{
|
||||
"distro_name": "debian",
|
||||
"distro_version": "bookworm",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "17",
|
||||
"image_sha": "ab4d1f0"
|
||||
"image_sha": "4c086b9"
|
||||
},
|
||||
{
|
||||
"distro_name": "debian",
|
||||
"distro_version": "bookworm",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "18",
|
||||
"image_sha": "ab4d1f0"
|
||||
"image_sha": "4c086b9"
|
||||
},
|
||||
{
|
||||
"distro_name": "debian",
|
||||
"distro_version": "bookworm",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "19",
|
||||
"image_sha": "ab4d1f0"
|
||||
"image_sha": "4c086b9"
|
||||
},
|
||||
{
|
||||
"distro_name": "debian",
|
||||
"distro_version": "bookworm",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "20",
|
||||
"image_sha": "ab4d1f0"
|
||||
"image_sha": "4c086b9"
|
||||
},
|
||||
{
|
||||
"distro_name": "debian",
|
||||
"distro_version": "trixie",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "14",
|
||||
"image_sha": "ab4d1f0"
|
||||
"image_sha": "4c086b9"
|
||||
},
|
||||
{
|
||||
"distro_name": "debian",
|
||||
"distro_version": "trixie",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "15",
|
||||
"image_sha": "ab4d1f0"
|
||||
"image_sha": "4c086b9"
|
||||
},
|
||||
{
|
||||
"distro_name": "debian",
|
||||
"distro_version": "trixie",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "20",
|
||||
"image_sha": "ab4d1f0"
|
||||
"image_sha": "4c086b9"
|
||||
},
|
||||
{
|
||||
"distro_name": "debian",
|
||||
"distro_version": "trixie",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "21",
|
||||
"image_sha": "ab4d1f0"
|
||||
"image_sha": "4c086b9"
|
||||
},
|
||||
{
|
||||
"distro_name": "debian",
|
||||
"distro_version": "trixie",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "22",
|
||||
"image_sha": "4c086b9"
|
||||
},
|
||||
{
|
||||
"distro_name": "rhel",
|
||||
"distro_version": "8",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "14",
|
||||
"image_sha": "ab4d1f0"
|
||||
"image_sha": "4c086b9"
|
||||
},
|
||||
{
|
||||
"distro_name": "rhel",
|
||||
"distro_version": "8",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "any",
|
||||
"image_sha": "ab4d1f0"
|
||||
"image_sha": "4c086b9"
|
||||
},
|
||||
{
|
||||
"distro_name": "rhel",
|
||||
"distro_version": "9",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "12",
|
||||
"image_sha": "ab4d1f0"
|
||||
"image_sha": "4c086b9",
|
||||
"package": true
|
||||
},
|
||||
{
|
||||
"distro_name": "rhel",
|
||||
"distro_version": "9",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "13",
|
||||
"image_sha": "ab4d1f0"
|
||||
"image_sha": "4c086b9"
|
||||
},
|
||||
{
|
||||
"distro_name": "rhel",
|
||||
"distro_version": "9",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "14",
|
||||
"image_sha": "ab4d1f0"
|
||||
"image_sha": "4c086b9"
|
||||
},
|
||||
{
|
||||
"distro_name": "rhel",
|
||||
"distro_version": "9",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "any",
|
||||
"image_sha": "ab4d1f0"
|
||||
"image_sha": "4c086b9"
|
||||
},
|
||||
{
|
||||
"distro_name": "rhel",
|
||||
"distro_version": "10",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "14",
|
||||
"image_sha": "ab4d1f0"
|
||||
"image_sha": "4c086b9"
|
||||
},
|
||||
{
|
||||
"distro_name": "rhel",
|
||||
"distro_version": "10",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "any",
|
||||
"image_sha": "ab4d1f0"
|
||||
"image_sha": "4c086b9"
|
||||
},
|
||||
{
|
||||
"distro_name": "ubuntu",
|
||||
"distro_version": "jammy",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "12",
|
||||
"image_sha": "ab4d1f0"
|
||||
"image_sha": "4c086b9",
|
||||
"package": true
|
||||
},
|
||||
{
|
||||
"distro_name": "ubuntu",
|
||||
"distro_version": "noble",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "13",
|
||||
"image_sha": "ab4d1f0"
|
||||
"image_sha": "4c086b9"
|
||||
},
|
||||
{
|
||||
"distro_name": "ubuntu",
|
||||
"distro_version": "noble",
|
||||
"compiler_name": "gcc",
|
||||
"compiler_version": "14",
|
||||
"image_sha": "ab4d1f0"
|
||||
"image_sha": "4c086b9"
|
||||
},
|
||||
{
|
||||
"distro_name": "ubuntu",
|
||||
"distro_version": "noble",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "16",
|
||||
"image_sha": "ab4d1f0"
|
||||
"image_sha": "4c086b9"
|
||||
},
|
||||
{
|
||||
"distro_name": "ubuntu",
|
||||
"distro_version": "noble",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "17",
|
||||
"image_sha": "ab4d1f0"
|
||||
"image_sha": "4c086b9"
|
||||
},
|
||||
{
|
||||
"distro_name": "ubuntu",
|
||||
"distro_version": "noble",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "18",
|
||||
"image_sha": "ab4d1f0"
|
||||
"image_sha": "4c086b9"
|
||||
},
|
||||
{
|
||||
"distro_name": "ubuntu",
|
||||
"distro_version": "noble",
|
||||
"compiler_name": "clang",
|
||||
"compiler_version": "19",
|
||||
"image_sha": "ab4d1f0"
|
||||
"image_sha": "4c086b9"
|
||||
}
|
||||
],
|
||||
"build_type": ["Debug", "Release"],
|
||||
|
||||
101
.github/workflows/build-nix-image.yml
vendored
Normal file
101
.github/workflows/build-nix-image.yml
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
name: Build Nix Docker image
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- develop
|
||||
paths:
|
||||
- ".github/workflows/build-nix-image.yml"
|
||||
- "docker/nix.Dockerfile"
|
||||
- "flake.nix"
|
||||
- "flake.lock"
|
||||
- "nix/**"
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/build-nix-image.yml"
|
||||
- "docker/nix.Dockerfile"
|
||||
- "flake.nix"
|
||||
- "flake.lock"
|
||||
- "nix/**"
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
env:
|
||||
UBUNTU_VERSION: "20.04"
|
||||
RHEL_VERSION: "9"
|
||||
DEBIAN_VERSION: "bookworm"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build and push Nix image (${{ matrix.distro }})
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- distro: nixos
|
||||
- distro: ubuntu
|
||||
- distro: rhel
|
||||
- distro: debian
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: Determine base image
|
||||
id: vars
|
||||
run: |
|
||||
case "${{ matrix.distro }}" in
|
||||
nixos)
|
||||
echo "base_image=nixos/nix:latest" >> $GITHUB_OUTPUT
|
||||
;;
|
||||
ubuntu)
|
||||
echo "base_image=ubuntu:${UBUNTU_VERSION}" >> $GITHUB_OUTPUT
|
||||
;;
|
||||
rhel)
|
||||
echo "base_image=registry.access.redhat.com/ubi${RHEL_VERSION}/ubi:latest" >> $GITHUB_OUTPUT
|
||||
;;
|
||||
debian)
|
||||
echo "base_image=debian:${DEBIAN_VERSION}" >> $GITHUB_OUTPUT
|
||||
;;
|
||||
esac
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
if: github.event_name == 'push'
|
||||
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Docker metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0
|
||||
with:
|
||||
images: ghcr.io/xrplf/ci/nix-${{ matrix.distro }}
|
||||
tags: |
|
||||
type=sha,prefix=sha-,format=short
|
||||
type=raw,value=latest
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
|
||||
with:
|
||||
context: .
|
||||
file: docker/nix.Dockerfile
|
||||
platforms: linux/amd64
|
||||
push: ${{ github.event_name == 'push' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: BASE_IMAGE=${{ steps.vars.outputs.base_image }}
|
||||
2
.github/workflows/check-pr-title.yml
vendored
2
.github/workflows/check-pr-title.yml
vendored
@@ -11,4 +11,4 @@ on:
|
||||
jobs:
|
||||
check_title:
|
||||
if: ${{ github.event.pull_request.draft != true }}
|
||||
uses: XRPLF/actions/.github/workflows/check-pr-title.yml@a5d8dd35be543365e90a11358447130c8763871d
|
||||
uses: XRPLF/actions/.github/workflows/check-pr-title.yml@291206777251b4d493641b5afbdf7c23009d2988
|
||||
|
||||
12
.github/workflows/on-pr.yml
vendored
12
.github/workflows/on-pr.yml
vendored
@@ -64,11 +64,13 @@ jobs:
|
||||
.github/workflows/reusable-build-test-config.yml
|
||||
.github/workflows/reusable-build-test.yml
|
||||
.github/workflows/reusable-clang-tidy.yml
|
||||
.github/workflows/reusable-package.yml
|
||||
.github/workflows/reusable-strategy-matrix.yml
|
||||
.github/workflows/reusable-test.yml
|
||||
.github/workflows/reusable-upload-recipe.yml
|
||||
.clang-tidy
|
||||
.codecov.yml
|
||||
cfg/**
|
||||
cmake/**
|
||||
conan/**
|
||||
external/**
|
||||
@@ -78,6 +80,10 @@ jobs:
|
||||
CMakeLists.txt
|
||||
conanfile.py
|
||||
conan.lock
|
||||
LICENSE.md
|
||||
package/**
|
||||
README.md
|
||||
|
||||
- name: Check whether to run
|
||||
# This step determines whether the rest of the workflow should
|
||||
# run. The rest of the workflow will run if this job runs AND at
|
||||
@@ -134,6 +140,11 @@ jobs:
|
||||
secrets:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
package:
|
||||
needs: [should-run, build-test]
|
||||
if: ${{ needs.should-run.outputs.go == 'true' }}
|
||||
uses: ./.github/workflows/reusable-package.yml
|
||||
|
||||
upload-recipe:
|
||||
needs:
|
||||
- should-run
|
||||
@@ -168,6 +179,7 @@ jobs:
|
||||
- check-rename
|
||||
- clang-tidy
|
||||
- build-test
|
||||
- package
|
||||
- upload-recipe
|
||||
- notify-clio
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
23
.github/workflows/on-tag.yml
vendored
23
.github/workflows/on-tag.yml
vendored
@@ -1,5 +1,5 @@
|
||||
# This workflow uploads the libxrpl recipe to the Conan remote when a versioned
|
||||
# tag is pushed.
|
||||
# This workflow uploads the libxrpl recipe to the Conan remote and builds
|
||||
# release packages when a versioned tag is pushed.
|
||||
name: Tag
|
||||
|
||||
on:
|
||||
@@ -22,3 +22,22 @@ jobs:
|
||||
secrets:
|
||||
remote_username: ${{ secrets.CONAN_REMOTE_USERNAME }}
|
||||
remote_password: ${{ secrets.CONAN_REMOTE_PASSWORD }}
|
||||
|
||||
build-test:
|
||||
if: ${{ github.repository == 'XRPLF/rippled' }}
|
||||
uses: ./.github/workflows/reusable-build-test.yml
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
os: [linux]
|
||||
with:
|
||||
ccache_enabled: false
|
||||
os: ${{ matrix.os }}
|
||||
strategy_matrix: minimal
|
||||
secrets:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
package:
|
||||
if: ${{ github.repository == 'XRPLF/rippled' }}
|
||||
needs: build-test
|
||||
uses: ./.github/workflows/reusable-package.yml
|
||||
|
||||
9
.github/workflows/on-trigger.yml
vendored
9
.github/workflows/on-trigger.yml
vendored
@@ -21,11 +21,13 @@ on:
|
||||
- ".github/workflows/reusable-build-test-config.yml"
|
||||
- ".github/workflows/reusable-build-test.yml"
|
||||
- ".github/workflows/reusable-clang-tidy.yml"
|
||||
- ".github/workflows/reusable-package.yml"
|
||||
- ".github/workflows/reusable-strategy-matrix.yml"
|
||||
- ".github/workflows/reusable-test.yml"
|
||||
- ".github/workflows/reusable-upload-recipe.yml"
|
||||
- ".clang-tidy"
|
||||
- ".codecov.yml"
|
||||
- "cfg/**"
|
||||
- "cmake/**"
|
||||
- "conan/**"
|
||||
- "external/**"
|
||||
@@ -35,6 +37,9 @@ on:
|
||||
- "CMakeLists.txt"
|
||||
- "conanfile.py"
|
||||
- "conan.lock"
|
||||
- "LICENSE.md"
|
||||
- "package/**"
|
||||
- "README.md"
|
||||
|
||||
# Run at 06:32 UTC on every day of the week from Monday through Friday. This
|
||||
# will force all dependencies to be rebuilt, which is useful to verify that
|
||||
@@ -95,3 +100,7 @@ jobs:
|
||||
secrets:
|
||||
remote_username: ${{ secrets.CONAN_REMOTE_USERNAME }}
|
||||
remote_password: ${{ secrets.CONAN_REMOTE_PASSWORD }}
|
||||
|
||||
package:
|
||||
needs: build-test
|
||||
uses: ./.github/workflows/reusable-package.yml
|
||||
|
||||
13
.github/workflows/reusable-build-test-config.yml
vendored
13
.github/workflows/reusable-build-test-config.yml
vendored
@@ -143,7 +143,6 @@ jobs:
|
||||
working-directory: ${{ env.BUILD_DIR }}
|
||||
env:
|
||||
BUILD_TYPE: ${{ inputs.build_type }}
|
||||
SANITIZERS: ${{ inputs.sanitizers }}
|
||||
CMAKE_ARGS: ${{ inputs.cmake_args }}
|
||||
run: |
|
||||
cmake \
|
||||
@@ -182,7 +181,7 @@ jobs:
|
||||
- name: Build the binary
|
||||
working-directory: ${{ env.BUILD_DIR }}
|
||||
env:
|
||||
BUILD_NPROC: ${{ steps.nproc.outputs.nproc }}
|
||||
BUILD_NPROC: ${{ runner.os == 'Linux' && '16' || steps.nproc.outputs.nproc }}
|
||||
BUILD_TYPE: ${{ inputs.build_type }}
|
||||
CMAKE_TARGET: ${{ inputs.cmake_target }}
|
||||
run: |
|
||||
@@ -284,8 +283,16 @@ jobs:
|
||||
|
||||
- name: Show test failure summary
|
||||
if: ${{ failure() && !inputs.build_only }}
|
||||
working-directory: ${{ runner.os == 'Windows' && format('{0}/{1}', env.BUILD_DIR, inputs.build_type) || env.BUILD_DIR }}
|
||||
env:
|
||||
WORKING_DIR: ${{ runner.os == 'Windows' && format('{0}\{1}', env.BUILD_DIR, inputs.build_type) || env.BUILD_DIR }}
|
||||
run: |
|
||||
if [ ! -d "${WORKING_DIR}" ]; then
|
||||
echo "Working directory '${WORKING_DIR}' does not exist."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
cd "${WORKING_DIR}"
|
||||
|
||||
if [ ! -f unittest.log ]; then
|
||||
echo "unittest.log not found; embedded tests may not have run."
|
||||
exit 0
|
||||
|
||||
79
.github/workflows/reusable-clang-tidy.yml
vendored
79
.github/workflows/reusable-clang-tidy.yml
vendored
@@ -29,7 +29,7 @@ jobs:
|
||||
if: ${{ inputs.check_only_changed }}
|
||||
permissions:
|
||||
contents: read
|
||||
uses: XRPLF/actions/.github/workflows/determine-tidy-files.yml@12f5dbc98a2260259a66970e57fa4d26fb7f285c
|
||||
uses: XRPLF/actions/.github/workflows/determine-tidy-files.yml@224f3c48d3014d082a1129237b8291ff0b0a331f
|
||||
|
||||
run-clang-tidy:
|
||||
name: Run clang tidy
|
||||
@@ -39,6 +39,7 @@ jobs:
|
||||
container: "ghcr.io/xrplf/ci/debian-trixie:clang-21-sha-53033a2"
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
@@ -92,6 +93,11 @@ jobs:
|
||||
set -o pipefail
|
||||
run-clang-tidy -j ${{ steps.nproc.outputs.nproc }} -p "${BUILD_DIR}" -quiet -fix -allow-no-checks ${TARGETS} 2>&1 | tee "${OUTPUT_FILE}"
|
||||
|
||||
- name: Print errors
|
||||
if: ${{ steps.run_clang_tidy.outcome != 'success' }}
|
||||
run: |
|
||||
sed '/error\||/!d' "${OUTPUT_FILE}"
|
||||
|
||||
- name: Upload clang-tidy output
|
||||
if: ${{ github.event.repository.visibility == 'public' && steps.run_clang_tidy.outcome != 'success' }}
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
@@ -100,13 +106,24 @@ jobs:
|
||||
archive: false
|
||||
retention-days: 30
|
||||
|
||||
- name: Check for changes
|
||||
id: files_changed
|
||||
continue-on-error: true
|
||||
run: |
|
||||
git diff --exit-code
|
||||
|
||||
- name: Fix style
|
||||
if: ${{ steps.files_changed.outcome != 'success' }}
|
||||
run: |
|
||||
pre-commit run --all-files || true
|
||||
|
||||
- name: Generate git diff
|
||||
if: ${{ steps.run_clang_tidy.outcome != 'success' }}
|
||||
if: ${{ steps.files_changed.outcome != 'success' }}
|
||||
run: |
|
||||
git diff | tee "${DIFF_FILE}"
|
||||
|
||||
- name: Upload clang-tidy diff output
|
||||
if: ${{ github.event.repository.visibility == 'public' && steps.run_clang_tidy.outcome != 'success' }}
|
||||
if: ${{ github.event.repository.visibility == 'public' && steps.files_changed.outcome != 'success' }}
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
path: ${{ env.DIFF_FILE }}
|
||||
@@ -116,24 +133,16 @@ jobs:
|
||||
- name: Write issue header
|
||||
if: ${{ steps.run_clang_tidy.outcome != 'success' }}
|
||||
run: |
|
||||
# Prepare issue body with clang-tidy output
|
||||
cat > "${ISSUE_FILE}" <<EOF
|
||||
## Clang-tidy Check Failed
|
||||
|
||||
**Workflow:** ${{ github.workflow }}
|
||||
**Run ID:** ${{ github.run_id }}
|
||||
**Commit:** ${{ github.sha }}
|
||||
**Branch/Ref:** ${{ github.ref }}
|
||||
**Triggered by:** ${{ github.actor }}
|
||||
|
||||
### Clang-tidy Output:
|
||||
\`\`\`
|
||||
EOF
|
||||
|
||||
- name: Append clang-tidy output to issue body
|
||||
- name: Append clang-tidy output to issue body (filter for errors and warnings)
|
||||
if: ${{ steps.run_clang_tidy.outcome != 'success' }}
|
||||
run: |
|
||||
# Append clang-tidy output (filter for errors and warnings)
|
||||
if [ -f "${OUTPUT_FILE}" ]; then
|
||||
# Extract lines containing 'error:', 'warning:', or 'note:'
|
||||
grep -E '(error:|warning:|note:)' "${OUTPUT_FILE}" > filtered-output.txt || true
|
||||
@@ -161,53 +170,21 @@ jobs:
|
||||
cat >> "${ISSUE_FILE}" <<EOF
|
||||
\`\`\`
|
||||
|
||||
**Workflow run:** ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
|
||||
---
|
||||
*This issue was automatically created by the clang-tidy workflow.*
|
||||
EOF
|
||||
|
||||
- name: Upload issue body artifact
|
||||
if: ${{ github.event.repository.visibility == 'public' && steps.run_clang_tidy.outcome != 'success' }}
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
- name: Create issue
|
||||
if: ${{ steps.run_clang_tidy.outcome != 'success' && inputs.create_issue_on_failure }}
|
||||
uses: XRPLF/actions/create-issue@36d450d12d301e8410c1b7936e5de70c291cbe36
|
||||
with:
|
||||
path: ${{ env.ISSUE_FILE }}
|
||||
archive: false
|
||||
retention-days: 30
|
||||
title: "Clang-tidy check failed"
|
||||
body_file: ${{ env.ISSUE_FILE }}
|
||||
labels: "Bug,Clang-tidy"
|
||||
assignees: "godexsoft,mathbunnyru"
|
||||
|
||||
- name: Fail if clang-tidy found issues
|
||||
if: ${{ steps.run_clang_tidy.outcome != 'success' }}
|
||||
run: |
|
||||
echo "Clang-tidy check failed!"
|
||||
exit 1
|
||||
|
||||
create-issue-on-failure:
|
||||
name: Create GitHub issue on failure
|
||||
runs-on: ubuntu-latest
|
||||
needs: [run-clang-tidy]
|
||||
if: ${{ always() && !cancelled() && inputs.create_issue_on_failure && needs.run-clang-tidy.result == 'failure' && github.event.repository.visibility == 'public' }}
|
||||
permissions:
|
||||
issues: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: Download clang-tidy-issue.md
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
name: ${{ env.ISSUE_FILE }}
|
||||
|
||||
- name: Create GitHub issue
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
# Create the issue
|
||||
gh issue create \
|
||||
--label "Bug,Clang-tidy" \
|
||||
--title "Clang-tidy check failed" \
|
||||
--body-file ./"${ISSUE_FILE}" \
|
||||
> create_issue.log
|
||||
|
||||
- name: Output created issue number
|
||||
run: |
|
||||
created_issue="$(sed 's|.*/||' create_issue.log)"
|
||||
echo "created_issue=$created_issue" >> $GITHUB_OUTPUT
|
||||
echo "Created issue #$created_issue"
|
||||
|
||||
99
.github/workflows/reusable-package.yml
vendored
Normal file
99
.github/workflows/reusable-package.yml
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
# Build Linux packages (DEB and RPM) from pre-built binary artifacts.
|
||||
# Discovers which configurations to package from linux.json (os entries
|
||||
# with "package": true) and fans out one job per entry. Today only
|
||||
# linux/amd64 is emitted; the architecture is hardcoded both here
|
||||
# (runner) and in generate.py.
|
||||
name: Package
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
pkg_release:
|
||||
description: "Package release number. Increment when repackaging the same executable."
|
||||
required: false
|
||||
type: string
|
||||
default: "1"
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
env:
|
||||
BUILD_DIR: build
|
||||
|
||||
jobs:
|
||||
generate-matrix:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
matrix: ${{ steps.generate.outputs.matrix }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
python-version: 3.13
|
||||
|
||||
- name: Generate packaging matrix
|
||||
id: generate
|
||||
working-directory: .github/scripts/strategy-matrix
|
||||
run: |
|
||||
./generate.py --packaging --config=linux.json >> "${GITHUB_OUTPUT}"
|
||||
|
||||
generate-version:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version: ${{ steps.version.outputs.version }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
sparse-checkout: |
|
||||
.github/actions/generate-version
|
||||
src/libxrpl/protocol/BuildInfo.cpp
|
||||
- name: Generate version
|
||||
id: version
|
||||
uses: ./.github/actions/generate-version
|
||||
|
||||
package:
|
||||
needs: [generate-matrix, generate-version]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}
|
||||
name: "${{ matrix.artifact_name }}"
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: ["self-hosted", "Linux", "X64", "heavy"]
|
||||
container: ${{ format('ghcr.io/xrplf/ci/{0}-{1}:{2}-{3}-sha-{4}', matrix.os.distro_name, matrix.os.distro_version, matrix.os.compiler_name, matrix.os.compiler_version, matrix.os.image_sha) }}
|
||||
timeout-minutes: 30
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: Download pre-built binary
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
name: ${{ matrix.artifact_name }}
|
||||
path: ${{ env.BUILD_DIR }}
|
||||
|
||||
- name: Make binary executable
|
||||
run: chmod +x "${BUILD_DIR}/xrpld"
|
||||
|
||||
- name: Build package
|
||||
env:
|
||||
PKG_VERSION: ${{ needs.generate-version.outputs.version }}
|
||||
PKG_RELEASE: ${{ inputs.pkg_release }}
|
||||
run: ./package/build_pkg.sh
|
||||
|
||||
- name: Upload package artifact
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
if: ${{ github.event.repository.visibility == 'public' }}
|
||||
with:
|
||||
name: ${{ matrix.artifact_name }}-pkg-${{ needs.generate-version.outputs.version }}
|
||||
path: |
|
||||
${{ env.BUILD_DIR }}/debbuild/*.deb
|
||||
${{ env.BUILD_DIR }}/debbuild/*.ddeb
|
||||
${{ env.BUILD_DIR }}/rpmbuild/RPMS/**/*.rpm
|
||||
if-no-files-found: error
|
||||
@@ -70,7 +70,11 @@ repos:
|
||||
rev: a42085ade523f591dca134379a595e7859986445 # frozen: v9.7.0
|
||||
hooks:
|
||||
- id: cspell # Spell check changed files
|
||||
exclude: (.config/cspell.config.yaml|^include/xrpl/protocol_autogen/(transactions|ledger_entries)/)
|
||||
exclude: |
|
||||
(?x)^(
|
||||
.config/cspell.config.yaml|
|
||||
include/xrpl/protocol_autogen/(transactions|ledger_entries)/.*
|
||||
)$
|
||||
- id: cspell # Spell check the commit message
|
||||
name: check commit message spelling
|
||||
args:
|
||||
|
||||
8
BUILD.md
8
BUILD.md
@@ -141,7 +141,7 @@ Alternatively, you can pull our recipes from the repository and export them loca
|
||||
|
||||
```bash
|
||||
# Define which recipes to export.
|
||||
recipes=('abseil' 'ed25519' 'grpc' 'm4' 'mpt-crypto' 'openssl' 'secp256k1' 'snappy' 'soci' 'wasm-xrplf' 'wasmi')
|
||||
recipes=('abseil' 'ed25519' 'mpt-crypto' 'openssl' 'secp256k1' 'snappy' 'soci' 'wasm-xrplf' 'wasmi')
|
||||
|
||||
# Selectively check out the recipes from our CCI fork.
|
||||
cd external
|
||||
@@ -530,16 +530,16 @@ stored inside the build directory, as either of:
|
||||
## Sanitizers
|
||||
|
||||
To build dependencies and xrpld with sanitizer instrumentation, set the
|
||||
`SANITIZERS` environment variable (only once before running conan and cmake) and use the `sanitizers` profile in conan:
|
||||
`SANITIZERS` environment variable when running `conan install` and use the `sanitizers` profile:
|
||||
|
||||
```bash
|
||||
export SANITIZERS=address,undefinedbehavior
|
||||
|
||||
conan install .. --output-folder . --profile:all sanitizers --build missing --settings build_type=Debug
|
||||
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Debug -Dxrpld=ON -Dtests=ON ..
|
||||
```
|
||||
|
||||
You can then build and test as usual, with the generated `xrpld` binary containing the sanitizer instrumentation. When you run it, it will report any sanitizer errors it detects in the console output.
|
||||
|
||||
See [Sanitizers docs](./docs/build/sanitizers.md) for more details.
|
||||
|
||||
## Options
|
||||
|
||||
@@ -134,6 +134,7 @@ endif()
|
||||
include(XrplCore)
|
||||
include(XrplProtocolAutogen)
|
||||
include(XrplInstall)
|
||||
include(XrplPackaging)
|
||||
include(XrplValidatorKeys)
|
||||
|
||||
if(tests)
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
# https://vl.ripple.com
|
||||
# https://unl.xrplf.org
|
||||
# http://127.0.0.1:8000
|
||||
# file:///etc/opt/xrpld/vl.txt
|
||||
# file:///etc/xrpld/vl.txt
|
||||
#
|
||||
# [validator_list_keys]
|
||||
#
|
||||
|
||||
@@ -527,6 +527,17 @@
|
||||
#
|
||||
# The current default (which is subject to change) is 300 seconds.
|
||||
#
|
||||
# verify_endpoints = <0 | 1>
|
||||
#
|
||||
# If set to 0, the server will skip validation of endpoint
|
||||
# addresses received in TMEndpoints peer protocol messages,
|
||||
# allowing addresses that are not publicly routable or have a
|
||||
# port of 0. The default is 1 (verification enabled).
|
||||
#
|
||||
# WARNING: Disabling this option is a security risk and should
|
||||
# only be used for local testing and debugging. Do not disable
|
||||
# on mainnet.
|
||||
#
|
||||
#
|
||||
# [transaction_queue] EXPERIMENTAL
|
||||
#
|
||||
@@ -1258,7 +1269,7 @@
|
||||
# default. Don't change this without understanding the consequences.
|
||||
#
|
||||
# Example:
|
||||
# account_reserve = 10000000 # 10 XRP
|
||||
# account_reserve = 1000000 # 1 XRP
|
||||
#
|
||||
# owner_reserve = <drops>
|
||||
#
|
||||
@@ -1270,7 +1281,7 @@
|
||||
# default. Don't change this without understanding the consequences.
|
||||
#
|
||||
# Example:
|
||||
# owner_reserve = 2000000 # 2 XRP
|
||||
# owner_reserve = 200000 # 0.2 XRP
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
@@ -1455,10 +1466,7 @@ admin = 127.0.0.1
|
||||
protocol = http
|
||||
|
||||
[port_peer]
|
||||
# Many servers still use the legacy port of 51235, so for backward-compatibility
|
||||
# we maintain that port number here. However, for new servers we recommend
|
||||
# changing this to the default port of 2459.
|
||||
port = 51235
|
||||
port = 2459
|
||||
ip = 0.0.0.0
|
||||
# alternatively, to accept connections on IPv4 + IPv6, use:
|
||||
#ip = ::
|
||||
|
||||
44
cmake/XrplPackaging.cmake
Normal file
44
cmake/XrplPackaging.cmake
Normal file
@@ -0,0 +1,44 @@
|
||||
#[===================================================================[
|
||||
Linux packaging support: 'package' target.
|
||||
|
||||
The packaging script (package/build_pkg.sh) installs to FHS-standard
|
||||
paths (/usr/bin, /etc/xrpld, etc.) regardless of CMAKE_INSTALL_PREFIX,
|
||||
so no prefix guard is needed here.
|
||||
#]===================================================================]
|
||||
if(NOT is_linux)
|
||||
message(STATUS "Packaging not supported on non-Linux hosts")
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED pkg_release)
|
||||
set(pkg_release 1)
|
||||
endif()
|
||||
|
||||
find_program(RPMBUILD_EXECUTABLE rpmbuild)
|
||||
find_program(DPKG_BUILDPACKAGE_EXECUTABLE dpkg-buildpackage)
|
||||
|
||||
if(NOT (RPMBUILD_EXECUTABLE OR DPKG_BUILDPACKAGE_EXECUTABLE))
|
||||
message(
|
||||
STATUS
|
||||
"Neither rpmbuild nor dpkg-buildpackage found; 'package' target not available"
|
||||
)
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(package_env
|
||||
SRC_DIR=${CMAKE_SOURCE_DIR}
|
||||
BUILD_DIR=${CMAKE_BINARY_DIR}
|
||||
PKG_VERSION=${xrpld_version}
|
||||
PKG_RELEASE=${pkg_release}
|
||||
)
|
||||
|
||||
add_custom_target(
|
||||
package
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E env ${package_env}
|
||||
${CMAKE_SOURCE_DIR}/package/build_pkg.sh
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
DEPENDS xrpld
|
||||
COMMENT "Building Linux package (deb/rpm inferred from host tooling)"
|
||||
VERBATIM
|
||||
)
|
||||
@@ -1,140 +1,33 @@
|
||||
#[===================================================================[
|
||||
Configure sanitizers based on environment variables.
|
||||
Apply sanitizer flags built by the Conan profile.
|
||||
|
||||
This module reads the following environment variables:
|
||||
- SANITIZERS: The sanitizers to enable. Possible values:
|
||||
- "address"
|
||||
- "address,undefinedbehavior"
|
||||
- "thread"
|
||||
- "thread,undefinedbehavior"
|
||||
- "undefinedbehavior"
|
||||
Parsing, validation, and flag construction are performed in conan/profiles/sanitizers.
|
||||
This module reads the following CMake variables injected by the Conan toolchain via extra_variables:
|
||||
|
||||
The compiler type and platform are detected in CompilationEnv.cmake.
|
||||
The sanitizer compile options are applied to the 'common' interface library
|
||||
which is linked to all targets in the project.
|
||||
- SANITIZERS: The active sanitizers (e.g. "address,undefinedbehavior").
|
||||
- SANITIZERS_COMPILER_FLAGS: Space-separated compiler flags.
|
||||
- SANITIZERS_LINKER_FLAGS: Space-separated linker flags.
|
||||
|
||||
Internal flag variables set by this module:
|
||||
|
||||
- SANITIZER_TYPES: List of sanitizer types to enable (e.g., "address",
|
||||
"thread", "undefined"). And two more flags for undefined behavior sanitizer (e.g., "float-divide-by-zero", "unsigned-integer-overflow").
|
||||
This list is joined with commas and passed to -fsanitize=<list>.
|
||||
|
||||
- SANITIZERS_COMPILE_FLAGS: Compiler flags for sanitizer instrumentation.
|
||||
Includes:
|
||||
* -fno-omit-frame-pointer: Preserves frame pointers for stack traces
|
||||
* -O1: Minimum optimization for reasonable performance
|
||||
* -fsanitize=<types>: Enables sanitizer instrumentation
|
||||
* -fsanitize-ignorelist=<path>: (Clang only) Compile-time ignorelist
|
||||
* -mcmodel=large/medium: (GCC only) Code model for large binaries
|
||||
* -Wno-stringop-overflow: (GCC only) Suppresses false positive warnings
|
||||
* -Wno-tsan: (For GCC TSAN combination only) Suppresses atomic_thread_fence warnings
|
||||
|
||||
- SANITIZERS_LINK_FLAGS: Linker flags for sanitizer runtime libraries.
|
||||
Includes:
|
||||
* -fsanitize=<types>: Links sanitizer runtime libraries
|
||||
* -mcmodel=large/medium: (GCC only) Matches compile-time code model
|
||||
|
||||
- SANITIZERS_RELOCATION_FLAGS: (GCC only, x86_64 only) Code model flags for linking.
|
||||
Used to handle large instrumented binaries on x86_64:
|
||||
* -mcmodel=large: For AddressSanitizer (prevents relocation errors)
|
||||
* -mcmodel=medium: For ThreadSanitizer (large model is incompatible)
|
||||
On ARM64, these flags are omitted since GCC does not support
|
||||
-mcmodel=large with -fPIC, and -mcmodel=medium does not exist.
|
||||
The flags are applied to the 'common' interface library which is linked to all targets in the project.
|
||||
#]===================================================================]
|
||||
|
||||
include_guard(GLOBAL)
|
||||
include(CompilationEnv)
|
||||
|
||||
# Read environment variable
|
||||
set(SANITIZERS "")
|
||||
if(DEFINED ENV{SANITIZERS})
|
||||
set(SANITIZERS "$ENV{SANITIZERS}")
|
||||
endif()
|
||||
|
||||
# Set SANITIZERS_ENABLED flag for use in other modules
|
||||
if(SANITIZERS MATCHES "address|thread|undefinedbehavior")
|
||||
set(SANITIZERS_ENABLED TRUE)
|
||||
else()
|
||||
if(NOT DEFINED SANITIZERS)
|
||||
set(SANITIZERS_ENABLED FALSE)
|
||||
return()
|
||||
endif()
|
||||
set(SANITIZERS_ENABLED TRUE)
|
||||
|
||||
# Sanitizers are not supported on Windows/MSVC
|
||||
if(is_msvc)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"Sanitizers are not supported on Windows/MSVC. "
|
||||
"Please unset the SANITIZERS environment variable."
|
||||
)
|
||||
endif()
|
||||
message(STATUS "=== Configuring Sanitizers ===")
|
||||
message(STATUS " SANITIZERS: ${SANITIZERS}")
|
||||
message(STATUS " Compile flags: ${SANITIZERS_COMPILER_FLAGS}")
|
||||
message(STATUS " Link flags: ${SANITIZERS_LINKER_FLAGS}")
|
||||
|
||||
message(STATUS "Configuring sanitizers: ${SANITIZERS}")
|
||||
|
||||
# Parse SANITIZERS value to determine which sanitizers to enable
|
||||
set(enable_asan FALSE)
|
||||
set(enable_tsan FALSE)
|
||||
set(enable_ubsan FALSE)
|
||||
|
||||
# Normalize SANITIZERS into a list
|
||||
set(san_list "${SANITIZERS}")
|
||||
string(REPLACE "," ";" san_list "${san_list}")
|
||||
separate_arguments(san_list)
|
||||
|
||||
foreach(san IN LISTS san_list)
|
||||
if(san STREQUAL "address")
|
||||
set(enable_asan TRUE)
|
||||
elseif(san STREQUAL "thread")
|
||||
set(enable_tsan TRUE)
|
||||
elseif(san STREQUAL "undefinedbehavior")
|
||||
set(enable_ubsan TRUE)
|
||||
else()
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"Unsupported sanitizer type: ${san}"
|
||||
"Supported: address, thread, undefinedbehavior and their combinations."
|
||||
)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Validate sanitizer compatibility
|
||||
if(enable_asan AND enable_tsan)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"AddressSanitizer and ThreadSanitizer are incompatible and cannot be enabled simultaneously. "
|
||||
"Use 'address' or 'thread', optionally with 'undefinedbehavior'."
|
||||
)
|
||||
endif()
|
||||
|
||||
# Frame pointer is required for meaningful stack traces. Sanitizers recommend minimum of -O1 for reasonable performance
|
||||
set(SANITIZERS_COMPILE_FLAGS "-fno-omit-frame-pointer" "-O1")
|
||||
|
||||
# Build the sanitizer flags list
|
||||
set(SANITIZER_TYPES)
|
||||
|
||||
if(enable_asan)
|
||||
list(APPEND SANITIZER_TYPES "address")
|
||||
elseif(enable_tsan)
|
||||
list(APPEND SANITIZER_TYPES "thread")
|
||||
endif()
|
||||
|
||||
if(enable_ubsan)
|
||||
# UB sanitizer flags
|
||||
list(APPEND SANITIZER_TYPES "undefined" "float-divide-by-zero")
|
||||
if(is_clang)
|
||||
# Clang supports additional UB checks. More info here
|
||||
# https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html
|
||||
list(APPEND SANITIZER_TYPES "unsigned-integer-overflow")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Configure code model for GCC on amd64 Use large code model for ASAN to avoid relocation errors Use medium code model
|
||||
# for TSAN (large is not compatible with TSAN)
|
||||
set(SANITIZERS_RELOCATION_FLAGS)
|
||||
|
||||
# Compiler-specific configuration
|
||||
# GCC with sanitizers is incompatible with mold, gold, and lld linkers.
|
||||
# Namely, the instrumented binary exceeds size limits imposed by these linkers.
|
||||
if(is_gcc)
|
||||
# Disable mold, gold and lld linkers for GCC with sanitizers Use default linker (bfd/ld) which is more lenient with
|
||||
# mixed code models This is needed since the size of instrumented binary exceeds the limits set by mold, lld and
|
||||
# gold linkers
|
||||
set(use_mold OFF CACHE BOOL "Use mold linker" FORCE)
|
||||
set(use_gold OFF CACHE BOOL "Use gold linker" FORCE)
|
||||
set(use_lld OFF CACHE BOOL "Use lld linker" FORCE)
|
||||
@@ -142,82 +35,62 @@ if(is_gcc)
|
||||
STATUS
|
||||
" Disabled mold, gold, and lld linkers for GCC with sanitizers"
|
||||
)
|
||||
|
||||
# Suppress false positive warnings in GCC with stringop-overflow
|
||||
list(APPEND SANITIZERS_COMPILE_FLAGS "-Wno-stringop-overflow")
|
||||
|
||||
if(is_amd64 AND enable_asan)
|
||||
message(STATUS " Using large code model (-mcmodel=large)")
|
||||
list(APPEND SANITIZERS_COMPILE_FLAGS "-mcmodel=large")
|
||||
list(APPEND SANITIZERS_RELOCATION_FLAGS "-mcmodel=large")
|
||||
elseif(enable_tsan)
|
||||
# GCC doesn't support atomic_thread_fence with tsan. Suppress warnings.
|
||||
list(APPEND SANITIZERS_COMPILE_FLAGS "-Wno-tsan")
|
||||
if(is_amd64)
|
||||
message(STATUS " Using medium code model (-mcmodel=medium)")
|
||||
list(APPEND SANITIZERS_COMPILE_FLAGS "-mcmodel=medium")
|
||||
list(APPEND SANITIZERS_RELOCATION_FLAGS "-mcmodel=medium")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Join sanitizer flags with commas for -fsanitize option
|
||||
list(JOIN SANITIZER_TYPES "," SANITIZER_TYPES_STR)
|
||||
|
||||
# Add sanitizer to compile and link flags
|
||||
list(APPEND SANITIZERS_COMPILE_FLAGS "-fsanitize=${SANITIZER_TYPES_STR}")
|
||||
set(SANITIZERS_LINK_FLAGS
|
||||
"${SANITIZERS_RELOCATION_FLAGS}"
|
||||
"-fsanitize=${SANITIZER_TYPES_STR}"
|
||||
)
|
||||
elseif(is_clang)
|
||||
# Add ignorelist for Clang (GCC doesn't support this) Use CMAKE_SOURCE_DIR to get the path to the ignorelist
|
||||
set(IGNORELIST_PATH
|
||||
"${CMAKE_SOURCE_DIR}/sanitizers/suppressions/sanitizer-ignorelist.txt"
|
||||
)
|
||||
if(NOT EXISTS "${IGNORELIST_PATH}")
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"Sanitizer ignorelist not found: ${IGNORELIST_PATH}"
|
||||
)
|
||||
endif()
|
||||
|
||||
list(
|
||||
APPEND SANITIZERS_COMPILE_FLAGS
|
||||
"-fsanitize-ignorelist=${IGNORELIST_PATH}"
|
||||
)
|
||||
message(STATUS " Using sanitizer ignorelist: ${IGNORELIST_PATH}")
|
||||
|
||||
# Join sanitizer flags with commas for -fsanitize option
|
||||
list(JOIN SANITIZER_TYPES "," SANITIZER_TYPES_STR)
|
||||
|
||||
# Add sanitizer to compile and link flags
|
||||
list(APPEND SANITIZERS_COMPILE_FLAGS "-fsanitize=${SANITIZER_TYPES_STR}")
|
||||
set(SANITIZERS_LINK_FLAGS "-fsanitize=${SANITIZER_TYPES_STR}")
|
||||
endif()
|
||||
|
||||
message(STATUS " Compile flags: ${SANITIZERS_COMPILE_FLAGS}")
|
||||
message(STATUS " Link flags: ${SANITIZERS_LINK_FLAGS}")
|
||||
# Flags arrive as space-separated strings; split into CMake lists before use
|
||||
separate_arguments(
|
||||
sanitizers_compiler_flags
|
||||
UNIX_COMMAND
|
||||
"${SANITIZERS_COMPILER_FLAGS}"
|
||||
)
|
||||
separate_arguments(
|
||||
sanitizers_linker_flags
|
||||
UNIX_COMMAND
|
||||
"${SANITIZERS_LINKER_FLAGS}"
|
||||
)
|
||||
|
||||
# Apply the sanitizer flags to the 'common' interface library This is the same library used by XrplCompiler.cmake
|
||||
target_compile_options(
|
||||
common
|
||||
INTERFACE
|
||||
$<$<COMPILE_LANGUAGE:CXX>:${SANITIZERS_COMPILE_FLAGS}>
|
||||
$<$<COMPILE_LANGUAGE:C>:${SANITIZERS_COMPILE_FLAGS}>
|
||||
$<$<COMPILE_LANGUAGE:CXX>:${sanitizers_compiler_flags}>
|
||||
$<$<COMPILE_LANGUAGE:C>:${sanitizers_compiler_flags}>
|
||||
)
|
||||
target_link_options(common INTERFACE ${sanitizers_linker_flags})
|
||||
|
||||
# Apply linker flags
|
||||
target_link_options(common INTERFACE ${SANITIZERS_LINK_FLAGS})
|
||||
# This module appends -fsanitize-ignorelist=<path> for Clang builds.
|
||||
# The ignorelist path contains CMAKE_SOURCE_DIR, so it must be set here, rather than in the Conan profile.
|
||||
# GCC does not support -fsanitize-ignorelist.
|
||||
if(is_clang)
|
||||
set(ignorelist_path
|
||||
"${CMAKE_SOURCE_DIR}/sanitizers/suppressions/sanitizer-ignorelist.txt"
|
||||
)
|
||||
if(NOT EXISTS "${ignorelist_path}")
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"Sanitizer ignorelist not found: ${ignorelist_path}"
|
||||
)
|
||||
endif()
|
||||
target_compile_options(
|
||||
common
|
||||
INTERFACE
|
||||
$<$<COMPILE_LANGUAGE:CXX>:-fsanitize-ignorelist=${ignorelist_path}>
|
||||
$<$<COMPILE_LANGUAGE:C>:-fsanitize-ignorelist=${ignorelist_path}>
|
||||
)
|
||||
message(STATUS " Ignorelist: ${ignorelist_path}")
|
||||
endif()
|
||||
|
||||
# Define SANITIZERS macro for BuildInfo.cpp
|
||||
set(sanitizers_list)
|
||||
if(enable_asan)
|
||||
if(SANITIZERS MATCHES "address")
|
||||
set(enable_asan ON)
|
||||
list(APPEND sanitizers_list "ASAN")
|
||||
endif()
|
||||
if(enable_tsan)
|
||||
if(SANITIZERS MATCHES "thread")
|
||||
set(enable_tsan ON)
|
||||
list(APPEND sanitizers_list "TSAN")
|
||||
endif()
|
||||
if(enable_ubsan)
|
||||
if(SANITIZERS MATCHES "undefinedbehavior")
|
||||
set(enable_ubsan ON)
|
||||
list(APPEND sanitizers_list "UBSAN")
|
||||
endif()
|
||||
|
||||
|
||||
@@ -10,4 +10,4 @@ pcpp>=1.30
|
||||
pyparsing>=3.0.0
|
||||
|
||||
# Template engine - used to generate C++ code from templates
|
||||
Mako>=1.2.0
|
||||
Mako>=1.2.2
|
||||
|
||||
24
conan.lock
24
conan.lock
@@ -1,38 +1,38 @@
|
||||
{
|
||||
"version": "0.5",
|
||||
"requires": [
|
||||
"zlib/1.3.1#cac0f6daea041b0ccf42934163defb20%1774439233.809",
|
||||
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1777558780.503",
|
||||
"xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1765850149.987",
|
||||
"sqlite3/3.51.0#66aa11eabd0e34954c5c1c061ad44abe%1774467355.988",
|
||||
"sqlite3/3.53.0#324ada52333108388a9a6108bfa96734%1776096494.149",
|
||||
"soci/4.0.3#fe32b9ad5eb47e79ab9e45a68f363945%1774450067.231",
|
||||
"snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1765850147.878",
|
||||
"secp256k1/0.7.1#481881709eb0bdd0185a12b912bbe8ad%1770910500.329",
|
||||
"rocksdb/10.5.1#4a197eca381a3e5ae8adf8cffa5aacd0%1765850186.86",
|
||||
"re2/20251105#8579cfd0bda4daf0683f9e3898f964b4%1774398111.888",
|
||||
"protobuf/6.33.5#d96d52ba5baaaa532f47bda866ad87a5%1774467363.12",
|
||||
"openssl/3.6.1#e6399de266349245a4542fc5f6c71552%1774458290.139",
|
||||
"nudb/2.0.9#11149c73f8f2baff9a0198fe25971fc7%1774883011.384",
|
||||
"openssl/3.6.2#4789bbf131b77d0515d15e094c8f697f%1778071755.506",
|
||||
"nudb/2.0.9#11149c73f8f2baff9a0198fe25971fc7%1775040983.408",
|
||||
"lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1765850143.914",
|
||||
"libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1765842973.492",
|
||||
"libbacktrace/cci.20210118#a7691bfccd8caaf66309df196790a5a1%1765842973.03",
|
||||
"libarchive/3.8.1#ffee18995c706e02bf96e7a2f7042e0d%1765850144.736",
|
||||
"jemalloc/5.3.0#e951da9cf599e956cebc117880d2d9f8%1729241615.244",
|
||||
"libarchive/3.8.7#c446109bd1f1d8ba7936c94189bc50e6%1776147552.838",
|
||||
"jemalloc/5.3.1#1fc58d55316041f10fbc1e8a2eae632a%1776700028.228",
|
||||
"gtest/1.17.0#5224b3b3ff3b4ce1133cbdd27d53ee7d%1768312129.152",
|
||||
"grpc/1.78.1#b1a9e74b145cc471bed4dc64dc6eb2c1%1774467387.342",
|
||||
"ed25519/2015.03#ae761bdc52730a843f0809bdf6c1b1f6%1765850143.772",
|
||||
"date/3.0.4#862e11e80030356b53c2c38599ceb32b%1765850143.772",
|
||||
"c-ares/1.34.6#545240bb1c40e2cacd4362d6b8967650%1774439234.681",
|
||||
"bzip2/1.0.8#c470882369c2d95c5c77e970c0c7e321%1765850143.837",
|
||||
"boost/1.90.0#d5e8defe7355494953be18524a7f135b%1769454080.269",
|
||||
"boost/1.91.0#ea540ca2133d831b560036aa24dece3c%1778050991.9",
|
||||
"abseil/20250127.0#bb0baf1f362bc4a725a24eddd419b8f7%1774365460.196"
|
||||
],
|
||||
"build_requires": [
|
||||
"zlib/1.3.1#cac0f6daea041b0ccf42934163defb20%1774439233.809",
|
||||
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1777558780.503",
|
||||
"strawberryperl/5.32.1.1#8d114504d172cfea8ea1662d09b6333e%1774447376.964",
|
||||
"protobuf/6.33.5#d96d52ba5baaaa532f47bda866ad87a5%1774467363.12",
|
||||
"nasm/2.16.01#31e26f2ee3c4346ecd347911bd126904%1765850144.707",
|
||||
"msys2/cci.latest#d22fe7b2808f5fd34d0a7923ace9c54f%1770657326.649",
|
||||
"m4/1.4.19#5d7a4994e5875d76faf7acf3ed056036%1774365463.87",
|
||||
"m4/1.4.19#4523e4347b55cd26ae918bd5770cab9a%1778062762.471",
|
||||
"cmake/4.3.0#b939a42e98f593fb34d3a8c5cc860359%1774439249.183",
|
||||
"b2/5.4.2#ffd6084a119587e70f11cd45d1a386e2%1774439233.447",
|
||||
"automake/1.16.5#b91b7c384c3deaa9d535be02da14d04f%1755524470.56",
|
||||
@@ -48,13 +48,13 @@
|
||||
"lz4/1.10.0"
|
||||
],
|
||||
"boost/[>=1.83.0 <1.91.0]": [
|
||||
"boost/1.90.0"
|
||||
"boost/1.91.0"
|
||||
],
|
||||
"sqlite3/[>=3.44 <4]": [
|
||||
"sqlite3/3.51.0"
|
||||
"sqlite3/3.53.0"
|
||||
],
|
||||
"boost/1.83.0": [
|
||||
"boost/1.90.0"
|
||||
"boost/1.91.0"
|
||||
],
|
||||
"lz4/[>=1.9.4 <2]": [
|
||||
"lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504"
|
||||
|
||||
@@ -3,3 +3,5 @@
|
||||
core:non_interactive=True
|
||||
core.download:parallel={{ os.cpu_count() }}
|
||||
core.upload:parallel={{ os.cpu_count() }}
|
||||
tools.files.download:retry=5
|
||||
tools.files.download:retry_wait=10
|
||||
|
||||
@@ -1 +1 @@
|
||||
include(sanitizers)
|
||||
include(sanitizers)
|
||||
|
||||
@@ -3,96 +3,120 @@ include(default)
|
||||
{% set arch = detect_api.detect_arch() %}
|
||||
{% set sanitizers = os.getenv("SANITIZERS") %}
|
||||
|
||||
[conf]
|
||||
{% if sanitizers %}
|
||||
{% if compiler == "gcc" %}
|
||||
{% if "address" in sanitizers or "thread" in sanitizers or "undefinedbehavior" in sanitizers %}
|
||||
{% set sanitizer_list = [] %}
|
||||
{% set defines = [] %}
|
||||
{% set model_code = "" %}
|
||||
{% set extra_cxxflags = ["-fno-omit-frame-pointer", "-O1", "-Wno-stringop-overflow"] %}
|
||||
{% if not sanitizers %}
|
||||
{# Sanitizers not configured; no additional settings needed #}
|
||||
{% else %}
|
||||
|
||||
{% if "address" in sanitizers %}
|
||||
{% set _ = sanitizer_list.append("address") %}
|
||||
{% if arch == "x86_64" %}
|
||||
{% set model_code = "-mcmodel=large" %}
|
||||
{% endif %}
|
||||
{% set _ = defines.append("BOOST_USE_ASAN")%}
|
||||
{% set _ = defines.append("BOOST_USE_UCONTEXT")%}
|
||||
{% elif "thread" in sanitizers %}
|
||||
{% set _ = sanitizer_list.append("thread") %}
|
||||
{% if arch == "x86_64" %}
|
||||
{% set model_code = "-mcmodel=medium" %}
|
||||
{% endif %}
|
||||
{% set _ = extra_cxxflags.append("-Wno-tsan") %}
|
||||
{% set _ = defines.append("BOOST_USE_TSAN")%}
|
||||
{% set _ = defines.append("BOOST_USE_UCONTEXT")%}
|
||||
{% endif %}
|
||||
{% if compiler == "msvc" %}
|
||||
{{ "Sanitizers are not supported on Windows/MSVC. Please unset the SANITIZERS environment variable." }}
|
||||
{% endif %}
|
||||
|
||||
{% if "undefinedbehavior" in sanitizers %}
|
||||
{% set _ = sanitizer_list.append("undefined") %}
|
||||
{% set _ = sanitizer_list.append("float-divide-by-zero") %}
|
||||
{% endif %}
|
||||
{% set known_sanitizers = ["address", "thread", "undefinedbehavior"] %}
|
||||
{% set provided_sanitizers = [] %}
|
||||
{% for san in sanitizers.split(",") %}
|
||||
{% set san = san.strip() %}
|
||||
{% if san not in known_sanitizers %}
|
||||
{{ "Unknown sanitizer in SANITIZERS: " ~ san }}
|
||||
{% endif %}
|
||||
{% set _ = provided_sanitizers.append(san) %}
|
||||
{% endfor %}
|
||||
|
||||
{% set sanitizer_flags = "-fsanitize=" ~ ",".join(sanitizer_list) ~ " " ~ model_code %}
|
||||
{% set enable_asan = "address" in provided_sanitizers %}
|
||||
{% set enable_tsan = "thread" in provided_sanitizers %}
|
||||
{% set enable_ubsan = "undefinedbehavior" in provided_sanitizers %}
|
||||
|
||||
tools.build:cxxflags+=['{{sanitizer_flags}} {{" ".join(extra_cxxflags)}}']
|
||||
tools.build:sharedlinkflags+=['{{sanitizer_flags}}']
|
||||
tools.build:exelinkflags+=['{{sanitizer_flags}}']
|
||||
tools.build:defines+={{defines}}
|
||||
{% endif %}
|
||||
{% elif compiler == "apple-clang" or compiler == "clang" %}
|
||||
{% if "address" in sanitizers or "thread" in sanitizers or "undefinedbehavior" in sanitizers %}
|
||||
{% set sanitizer_list = [] %}
|
||||
{% set defines = [] %}
|
||||
{% set extra_cxxflags = ["-fno-omit-frame-pointer", "-O1"] %}
|
||||
{% if enable_asan and enable_tsan %}
|
||||
{{ "AddressSanitizer and ThreadSanitizer are incompatible and cannot be enabled simultaneously." }}
|
||||
{% endif %}
|
||||
|
||||
{% if "address" in sanitizers %}
|
||||
{% set _ = sanitizer_list.append("address") %}
|
||||
{% set _ = defines.append("BOOST_USE_ASAN")%}
|
||||
{% set _ = defines.append("BOOST_USE_UCONTEXT")%}
|
||||
{% elif "thread" in sanitizers %}
|
||||
{% set _ = sanitizer_list.append("thread") %}
|
||||
{% set _ = defines.append("BOOST_USE_TSAN")%}
|
||||
{% set _ = defines.append("BOOST_USE_UCONTEXT")%}
|
||||
{% endif %}
|
||||
{% set sanitizer_types = [] %}
|
||||
{% set defines = [] %}
|
||||
|
||||
{% if "undefinedbehavior" in sanitizers %}
|
||||
{% set _ = sanitizer_list.append("undefined") %}
|
||||
{% set _ = sanitizer_list.append("float-divide-by-zero") %}
|
||||
{% set _ = sanitizer_list.append("unsigned-integer-overflow") %}
|
||||
{% endif %}
|
||||
{% if enable_asan %}
|
||||
{% set _ = sanitizer_types.append("address") %}
|
||||
{% set _ = defines.append("BOOST_USE_ASAN") %}
|
||||
{% set _ = defines.append("BOOST_USE_UCONTEXT") %}
|
||||
{% elif enable_tsan %}
|
||||
{% set _ = sanitizer_types.append("thread") %}
|
||||
{% set _ = defines.append("BOOST_USE_TSAN") %}
|
||||
{% set _ = defines.append("BOOST_USE_UCONTEXT") %}
|
||||
{% endif %}
|
||||
|
||||
{% set sanitizer_flags = "-fsanitize=" ~ ",".join(sanitizer_list) %}
|
||||
|
||||
tools.build:cxxflags+=['{{sanitizer_flags}} {{" ".join(extra_cxxflags)}}']
|
||||
tools.build:sharedlinkflags+=['{{sanitizer_flags}}']
|
||||
tools.build:exelinkflags+=['{{sanitizer_flags}}']
|
||||
tools.build:defines+={{defines}}
|
||||
{% endif %}
|
||||
{% if enable_ubsan %}
|
||||
{% set _ = sanitizer_types.append("undefined") %}
|
||||
{% set _ = sanitizer_types.append("float-divide-by-zero") %}
|
||||
{# Clang supports additional UB checks beyond the GCC baseline #}
|
||||
{% if compiler == "clang" or compiler == "apple-clang" %}
|
||||
{% set _ = sanitizer_types.append("unsigned-integer-overflow") %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{# Frame pointer required for meaningful stack traces; -O1 for reasonable performance #}
|
||||
{% set compile_flags = ["-fno-omit-frame-pointer", "-O1"] %}
|
||||
|
||||
{% if compiler == "gcc" %}
|
||||
{# Suppress false positive warnings with GCC #}
|
||||
{% set _ = compile_flags.append("-Wno-stringop-overflow") %}
|
||||
|
||||
{% set relocation_flags = [] %}
|
||||
|
||||
{% if arch == "x86_64" and enable_asan %}
|
||||
{# Large code model prevents relocation errors in instrumented ASAN binaries #}
|
||||
{% set _ = compile_flags.append("-mcmodel=large") %}
|
||||
{% set _ = relocation_flags.append("-mcmodel=large") %}
|
||||
{% elif enable_tsan %}
|
||||
{# GCC doesn't support atomic_thread_fence with TSAN; suppress warnings #}
|
||||
{% set _ = compile_flags.append("-Wno-tsan") %}
|
||||
{% if arch == "x86_64" %}
|
||||
{# Medium code model for TSAN; large is incompatible #}
|
||||
{% set _ = compile_flags.append("-mcmodel=medium") %}
|
||||
{% set _ = relocation_flags.append("-mcmodel=medium") %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% set fsanitize = "-fsanitize=" ~ ",".join(sanitizer_types) %}
|
||||
{% set _ = compile_flags.append(fsanitize) %}
|
||||
{% set _ = relocation_flags.append(fsanitize) %}
|
||||
|
||||
{% set sanitizer_compiler_flags = " ".join(compile_flags) %}
|
||||
{% set sanitizer_linker_flags = " ".join(relocation_flags) %}
|
||||
{% elif compiler == "clang" or compiler == "apple-clang" %}
|
||||
{% set fsanitize = "-fsanitize=" ~ ",".join(sanitizer_types) %}
|
||||
{% set _ = compile_flags.append(fsanitize) %}
|
||||
|
||||
{% set sanitizer_compiler_flags = " ".join(compile_flags) %}
|
||||
{% set sanitizer_linker_flags = fsanitize %}
|
||||
{% endif %}
|
||||
|
||||
[conf]
|
||||
tools.build:defines+={{defines}}
|
||||
tools.build:cxxflags+=['{{sanitizer_compiler_flags}}']
|
||||
tools.build:sharedlinkflags+=['{{sanitizer_linker_flags}}']
|
||||
tools.build:exelinkflags+=['{{sanitizer_linker_flags}}']
|
||||
|
||||
tools.info.package_id:confs+=["tools.build:cxxflags", "tools.build:exelinkflags", "tools.build:sharedlinkflags", "tools.build:defines"]
|
||||
|
||||
# &: means "apply only to the consumer/root package"
|
||||
&:tools.cmake.cmaketoolchain:extra_variables={"SANITIZERS": "{{sanitizers}}", "SANITIZERS_COMPILER_FLAGS": "{{sanitizer_compiler_flags}}", "SANITIZERS_LINKER_FLAGS": "{{sanitizer_linker_flags}}"}
|
||||
|
||||
[options]
|
||||
{% if sanitizers %}
|
||||
{% if "address" in sanitizers %}
|
||||
# Build Boost.Context with ucontext backend (not fcontext) so that
|
||||
# ASAN fiber-switching annotations (__sanitizer_start/finish_switch_fiber)
|
||||
# are compiled into the library. fcontext (assembly) has no ASAN support.
|
||||
# define=BOOST_USE_ASAN=1 is critical: it must be defined when building
|
||||
# Boost.Context itself so the ucontext backend compiles in the ASAN annotations.
|
||||
boost/*:extra_b2_flags=context-impl=ucontext address-sanitizer=on define=BOOST_USE_ASAN=1
|
||||
boost/*:without_context=False
|
||||
# Boost stacktrace fails to build with some sanitizers
|
||||
boost/*:without_stacktrace=True
|
||||
{% elif "thread" in sanitizers %}
|
||||
# Build Boost.Context with ucontext backend for TSAN. fcontext (assembly)
|
||||
# has no TSAN annotations, so without this the BOOST_USE_TSAN/BOOST_USE_UCONTEXT
|
||||
# defines in [conf] would be ineffective.
|
||||
boost/*:extra_b2_flags=context-impl=ucontext thread-sanitizer=on define=BOOST_USE_TSAN=1
|
||||
boost/*:without_context=False
|
||||
boost/*:without_stacktrace=True
|
||||
{% endif %}
|
||||
{% if enable_asan %}
|
||||
# Build Boost.Context with ucontext backend (not fcontext) so that
|
||||
# ASAN fiber-switching annotations (__sanitizer_start/finish_switch_fiber)
|
||||
# are compiled into the library. fcontext (assembly) has no ASAN support.
|
||||
# define=BOOST_USE_ASAN=1 is critical: it must be defined when building
|
||||
# Boost.Context itself so the ucontext backend compiles in the ASAN annotations.
|
||||
boost/*:extra_b2_flags=context-impl=ucontext address-sanitizer=on define=BOOST_USE_ASAN=1
|
||||
boost/*:without_context=False
|
||||
# Boost stacktrace fails to build with some sanitizers
|
||||
boost/*:without_stacktrace=True
|
||||
{% elif enable_tsan %}
|
||||
# Build Boost.Context with ucontext backend for TSAN. fcontext (assembly)
|
||||
# has no TSAN annotations, so without this the BOOST_USE_TSAN/BOOST_USE_UCONTEXT
|
||||
# defines in [conf] would be ineffective.
|
||||
boost/*:extra_b2_flags=context-impl=ucontext thread-sanitizer=on define=BOOST_USE_TSAN=1
|
||||
boost/*:without_context=False
|
||||
boost/*:without_stacktrace=True
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
14
conanfile.py
14
conanfile.py
@@ -1,4 +1,3 @@
|
||||
import os
|
||||
import re
|
||||
|
||||
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
|
||||
@@ -30,12 +29,12 @@ class Xrpl(ConanFile):
|
||||
requires = [
|
||||
"ed25519/2015.03",
|
||||
"grpc/1.78.1",
|
||||
"libarchive/3.8.1",
|
||||
"libarchive/3.8.7",
|
||||
"nudb/2.0.9",
|
||||
"openssl/3.6.1",
|
||||
"openssl/3.6.2",
|
||||
"secp256k1/0.7.1",
|
||||
"soci/4.0.3",
|
||||
"zlib/1.3.1",
|
||||
"zlib/1.3.2",
|
||||
]
|
||||
|
||||
test_requires = [
|
||||
@@ -57,6 +56,7 @@ class Xrpl(ConanFile):
|
||||
"tests": False,
|
||||
"unity": False,
|
||||
"xrpld": False,
|
||||
"boost/*:without_cobalt": True,
|
||||
"boost/*:without_context": False,
|
||||
"boost/*:without_coroutine": True,
|
||||
"boost/*:without_coroutine2": False,
|
||||
@@ -130,13 +130,13 @@ class Xrpl(ConanFile):
|
||||
self.options["boost"].without_cobalt = True
|
||||
|
||||
def requirements(self):
|
||||
self.requires("boost/1.90.0", force=True, transitive_headers=True)
|
||||
self.requires("boost/1.91.0", force=True, transitive_headers=True)
|
||||
self.requires("date/3.0.4", transitive_headers=True)
|
||||
self.requires("lz4/1.10.0", force=True)
|
||||
self.requires("protobuf/6.33.5", force=True)
|
||||
self.requires("sqlite3/3.51.0", force=True)
|
||||
self.requires("sqlite3/3.53.0", force=True)
|
||||
if self.options.jemalloc:
|
||||
self.requires("jemalloc/5.3.0")
|
||||
self.requires("jemalloc/5.3.1")
|
||||
if self.options.rocksdb:
|
||||
self.requires("rocksdb/10.5.1")
|
||||
self.requires("xxhash/0.8.3", transitive_headers=True)
|
||||
|
||||
@@ -63,6 +63,7 @@ words:
|
||||
- Bougalis
|
||||
- Britto
|
||||
- Btrfs
|
||||
- Buildx
|
||||
- canonicality
|
||||
- changespq
|
||||
- checkme
|
||||
@@ -71,6 +72,7 @@ words:
|
||||
- citardauq
|
||||
- clawback
|
||||
- clawbacks
|
||||
- cmaketoolchain
|
||||
- coeffs
|
||||
- coldwallet
|
||||
- compr
|
||||
@@ -97,12 +99,15 @@ words:
|
||||
- desync
|
||||
- desynced
|
||||
- determ
|
||||
- disablerepo
|
||||
- distro
|
||||
- doxyfile
|
||||
- dxrpl
|
||||
- enabled
|
||||
- enablerepo
|
||||
- endmacro
|
||||
- exceptioned
|
||||
- EXPECT_STREQ
|
||||
- Falco
|
||||
- fcontext
|
||||
- finalizers
|
||||
@@ -114,6 +119,7 @@ words:
|
||||
- gcovr
|
||||
- ghead
|
||||
- Gnutella
|
||||
- godexsoft
|
||||
- gpgcheck
|
||||
- gpgkey
|
||||
- hotwallet
|
||||
@@ -159,6 +165,7 @@ words:
|
||||
- Merkle
|
||||
- Metafuncton
|
||||
- misprediction
|
||||
- missingok
|
||||
- mptbalance
|
||||
- MPTDEX
|
||||
- mptflags
|
||||
@@ -190,7 +197,9 @@ words:
|
||||
- NOLINT
|
||||
- NOLINTNEXTLINE
|
||||
- nonxrp
|
||||
- noreplace
|
||||
- noripple
|
||||
- notifempty
|
||||
- nudb
|
||||
- nullptr
|
||||
- nunl
|
||||
@@ -210,6 +219,7 @@ words:
|
||||
- preauthorize
|
||||
- preauthorizes
|
||||
- preclaim
|
||||
- preun
|
||||
- protobuf
|
||||
- protos
|
||||
- ptrs
|
||||
@@ -244,12 +254,14 @@ words:
|
||||
- sfields
|
||||
- shamap
|
||||
- shamapitem
|
||||
- shlibs
|
||||
- sidechain
|
||||
- SIGGOOD
|
||||
- sle
|
||||
- sles
|
||||
- soci
|
||||
- socidb
|
||||
- SRPMS
|
||||
- sslws
|
||||
- statsd
|
||||
- STATSDCOLLECTOR
|
||||
@@ -277,8 +289,8 @@ words:
|
||||
- txn
|
||||
- txns
|
||||
- txs
|
||||
- UBSAN
|
||||
- ubsan
|
||||
- UBSAN
|
||||
- umant
|
||||
- unacquired
|
||||
- unambiguity
|
||||
@@ -315,7 +327,6 @@ words:
|
||||
- xbridge
|
||||
- xchain
|
||||
- ximinez
|
||||
- EXPECT_STREQ
|
||||
- XMACRO
|
||||
- xrpkuwait
|
||||
- xrpl
|
||||
@@ -323,3 +334,4 @@ words:
|
||||
- xrplf
|
||||
- xxhash
|
||||
- xxhasher
|
||||
- CGNAT
|
||||
|
||||
66
docker/nix.Dockerfile
Normal file
66
docker/nix.Dockerfile
Normal file
@@ -0,0 +1,66 @@
|
||||
ARG BASE_IMAGE=nixos/nix:latest
|
||||
|
||||
# Nix builder
|
||||
FROM nixos/nix:latest AS builder-source
|
||||
|
||||
RUN mkdir -p ~/.config/nix && \
|
||||
echo "experimental-features = nix-command flakes" >> ~/.config/nix/nix.conf
|
||||
|
||||
# Copy our source and setup our working dir.
|
||||
COPY nix/ci-env.nix /tmp/build/nix/ci-env.nix
|
||||
COPY nix/packages.nix /tmp/build/nix/packages.nix
|
||||
COPY nix/utils.nix /tmp/build/nix/utils.nix
|
||||
COPY flake.nix /tmp/build/
|
||||
COPY flake.lock /tmp/build/
|
||||
WORKDIR /tmp/build
|
||||
|
||||
FROM builder-source AS builder
|
||||
|
||||
# Build our Nix CI environment (all build tools in a single store path)
|
||||
RUN nix \
|
||||
--option filter-syscalls false \
|
||||
build
|
||||
|
||||
# Copy the Nix store closure into a directory. The Nix store closure is the
|
||||
# entire set of Nix store values that we need for our build.
|
||||
RUN mkdir /tmp/nix-store-closure && \
|
||||
cp -R $(nix-store -qR result/) /tmp/nix-store-closure
|
||||
|
||||
# Final image
|
||||
FROM ${BASE_IMAGE}
|
||||
|
||||
# bash is not located at /bin/bash in nixos/nix, so we need to create a symlink to it.
|
||||
RUN if [ -d /nix ]; then \
|
||||
ln -s /root/.nix-profile/bin/bash /bin/bash; \
|
||||
fi
|
||||
|
||||
# Use Bash as the default shell for RUN commands, using the options
|
||||
# `set -o errexit -o pipefail`, and as the entrypoint.
|
||||
SHELL ["/bin/bash", "-e", "-o", "pipefail", "-c"]
|
||||
ENTRYPOINT ["/bin/bash"]
|
||||
|
||||
# Copy /nix/store and the env symlink tree
|
||||
COPY --from=builder /tmp/nix-store-closure /nix/store
|
||||
COPY --from=builder /tmp/build/result /nix/ci-env
|
||||
|
||||
ENV PATH="/nix/ci-env/bin:$PATH"
|
||||
|
||||
RUN <<EOF
|
||||
ccache --version
|
||||
clang-format --version
|
||||
cmake --version
|
||||
conan --version
|
||||
g++ --version
|
||||
gcc --version
|
||||
gcovr --version
|
||||
git --version
|
||||
make --version
|
||||
mold --version
|
||||
ninja --version
|
||||
perl --version
|
||||
pkg-config --version
|
||||
pre-commit --version
|
||||
python3 --version
|
||||
run-clang-tidy --help
|
||||
vim --version
|
||||
EOF
|
||||
45
docs/build/sanitizers.md
vendored
45
docs/build/sanitizers.md
vendored
@@ -1,15 +1,17 @@
|
||||
# Sanitizer Configuration for Xrpld
|
||||
|
||||
This document explains how to properly configure and run sanitizers (AddressSanitizer, undefinedbehaviorSanitizer, ThreadSanitizer) with the xrpld project.
|
||||
This document explains how to properly configure and run sanitizers (`AddressSanitizer`, `UndefinedBehaviorSanitizer`, `ThreadSanitizer`) with the xrpld project.
|
||||
Corresponding suppression files are located in the `sanitizers/suppressions` directory.
|
||||
|
||||
> [!CAUTION]
|
||||
> Do not mix Address and Thread sanitizers - they are incompatible.
|
||||
> Also, we don't yet support MSVC sanitizers, so this is only for Clang/GCC builds.
|
||||
|
||||
- [Sanitizer Configuration for Xrpld](#sanitizer-configuration-for-xrpld)
|
||||
- [Building with Sanitizers](#building-with-sanitizers)
|
||||
- [Summary](#summary)
|
||||
- [Build steps:](#build-steps)
|
||||
- [Install dependencies](#install-dependencies)
|
||||
- [Call CMake](#call-cmake)
|
||||
- [Build](#build)
|
||||
- [Running Tests with Sanitizers](#running-tests-with-sanitizers)
|
||||
- [AddressSanitizer (ASAN)](#addresssanitizer-asan)
|
||||
- [ThreadSanitizer (TSan)](#threadsanitizer-tsan)
|
||||
@@ -33,9 +35,13 @@ Corresponding suppression files are located in the `sanitizers/suppressions` dir
|
||||
Follow the same instructions as mentioned in [BUILD.md](../../BUILD.md) but with the following changes:
|
||||
|
||||
1. Make sure you have a clean build directory.
|
||||
2. Set the `SANITIZERS` environment variable before calling conan install and cmake. Only set it once. Make sure both conan and cmake read the same values.
|
||||
2. Set the `SANITIZERS` environment variable before calling `conan install`. Only set it once.
|
||||
Example: `export SANITIZERS=address,undefinedbehavior`
|
||||
3. Optionally use `--profile:all sanitizers` with Conan to build dependencies with sanitizer instrumentation. [!NOTE]Building with sanitizer-instrumented dependencies is slower but produces fewer false positives.
|
||||
3. Use `--profile:all sanitizers` with Conan to build dependencies with sanitizer instrumentation.
|
||||
|
||||
> [!NOTE]
|
||||
> Building with sanitizer-instrumented dependencies is slower but produces fewer false positives.
|
||||
|
||||
4. Set `ASAN_OPTIONS`, `LSAN_OPTIONS`, `UBSAN_OPTIONS` and `TSAN_OPTIONS` environment variables to configure sanitizer behavior when running executables. [More details below](#running-tests-with-sanitizers).
|
||||
|
||||
---
|
||||
@@ -51,36 +57,13 @@ cd .build
|
||||
|
||||
#### Install dependencies
|
||||
|
||||
The `SANITIZERS` environment variable is used by both Conan and CMake.
|
||||
The `SANITIZERS` environment variable is used during `conan install` command.
|
||||
|
||||
```bash
|
||||
export SANITIZERS=address,undefinedbehavior
|
||||
# Standard build (without instrumenting dependencies)
|
||||
conan install .. --output-folder . --build missing --settings build_type=Debug
|
||||
|
||||
# Or with sanitizer-instrumented dependencies (takes longer but fewer false positives)
|
||||
conan install .. --output-folder . --profile:all sanitizers --build missing --settings build_type=Debug
|
||||
SANITIZERS=address,undefinedbehavior conan install .. --output-folder . --build missing --settings build_type=Debug --profile:all sanitizers
|
||||
```
|
||||
|
||||
[!CAUTION]
|
||||
Do not mix Address and Thread sanitizers - they are incompatible.
|
||||
|
||||
Since you already set the `SANITIZERS` environment variable when running Conan, same values will be read for the next part.
|
||||
|
||||
#### Call CMake
|
||||
|
||||
```bash
|
||||
cmake .. -G Ninja \
|
||||
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \
|
||||
-DCMAKE_BUILD_TYPE=Debug \
|
||||
-Dtests=ON -Dxrpld=ON
|
||||
```
|
||||
|
||||
#### Build
|
||||
|
||||
```bash
|
||||
cmake --build . --parallel 4
|
||||
```
|
||||
Proceed with the rest of the build instructions as mentioned in [BUILD.md](../../BUILD.md).
|
||||
|
||||
## Running Tests with Sanitizers
|
||||
|
||||
|
||||
26
flake.lock
generated
26
flake.lock
generated
@@ -2,11 +2,11 @@
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1769461804,
|
||||
"narHash": "sha256-6h5sROT/3CTHvzPy9koKBmoCa2eJKh4fzQK8eYFEgl8=",
|
||||
"lastModified": 1777954456,
|
||||
"narHash": "sha256-hGdgeU2Nk87RAuZyYjyDjFL6LK7dAZN5RE9+hrDTkDU=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "b579d443b37c9c5373044201ea77604e37e748c8",
|
||||
"rev": "549bd84d6279f9852cae6225e372cc67fb91a4c1",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -15,9 +15,27 @@
|
||||
"type": "indirect"
|
||||
}
|
||||
},
|
||||
"nixpkgs-glibc231": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1593520194,
|
||||
"narHash": "sha256-+TZW+2I7kLL9JglPNOagm1ywjf9ua0JYGoptq/dzVn0=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "9cd98386a38891d1074fc18036b842dc4416f562",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "9cd98386a38891d1074fc18036b842dc4416f562",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs"
|
||||
"nixpkgs": "nixpkgs",
|
||||
"nixpkgs-glibc231": "nixpkgs-glibc231"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
13
flake.nix
13
flake.nix
@@ -2,15 +2,24 @@
|
||||
description = "Nix related things for xrpld";
|
||||
inputs = {
|
||||
nixpkgs.url = "nixpkgs/nixos-unstable";
|
||||
# nixpkgs snapshot (2020-06-30) that shipped glibc 2.31 as the primary
|
||||
# version — matches the system libc on Ubuntu 20.04 LTS. Imported
|
||||
# manually (flake = false) because this revision predates nixpkgs'
|
||||
# own flake.nix.
|
||||
nixpkgs-glibc231 = {
|
||||
url = "github:NixOS/nixpkgs/9cd98386a38891d1074fc18036b842dc4416f562";
|
||||
flake = false;
|
||||
};
|
||||
};
|
||||
|
||||
outputs =
|
||||
{ nixpkgs, ... }:
|
||||
{ nixpkgs, nixpkgs-glibc231, ... }:
|
||||
let
|
||||
forEachSystem = (import ./nix/utils.nix { inherit nixpkgs; }).forEachSystem;
|
||||
forEachSystem = import ./nix/utils.nix { inherit nixpkgs nixpkgs-glibc231; };
|
||||
in
|
||||
{
|
||||
devShells = forEachSystem (import ./nix/devshell.nix);
|
||||
packages = forEachSystem (import ./nix/ci-env.nix);
|
||||
formatter = forEachSystem ({ pkgs, ... }: pkgs.nixfmt);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -148,17 +148,23 @@ public:
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr E const&
|
||||
error() const
|
||||
error() const&
|
||||
{
|
||||
return Base::error();
|
||||
}
|
||||
|
||||
constexpr E&
|
||||
error()
|
||||
[[nodiscard]] constexpr E&
|
||||
error() &
|
||||
{
|
||||
return Base::error();
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr E&&
|
||||
error() &&
|
||||
{
|
||||
return std::move(Base::error());
|
||||
}
|
||||
|
||||
constexpr explicit
|
||||
operator bool() const
|
||||
{
|
||||
@@ -215,17 +221,23 @@ public:
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr E const&
|
||||
error() const
|
||||
error() const&
|
||||
{
|
||||
return Base::error();
|
||||
}
|
||||
|
||||
constexpr E&
|
||||
error()
|
||||
[[nodiscard]] constexpr E&
|
||||
error() &
|
||||
{
|
||||
return Base::error();
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr E&&
|
||||
error() &&
|
||||
{
|
||||
return std::move(Base::error());
|
||||
}
|
||||
|
||||
constexpr explicit
|
||||
operator bool() const
|
||||
{
|
||||
|
||||
@@ -406,8 +406,8 @@ private:
|
||||
// pointer. The low bit must be masked to zero when converting back to a
|
||||
// pointer. If the low bit is '1', this is a weak pointer.
|
||||
std::uintptr_t tp_{0};
|
||||
static constexpr std::uintptr_t kTAG_MASK = 1;
|
||||
static constexpr std::uintptr_t kPTR_MASK = ~kTAG_MASK;
|
||||
static constexpr std::uintptr_t kTagMask = 1;
|
||||
static constexpr std::uintptr_t kPtrMask = ~kTagMask;
|
||||
|
||||
private:
|
||||
/** Return the raw pointer held by this object.
|
||||
|
||||
@@ -567,14 +567,14 @@ template <class T>
|
||||
bool
|
||||
SharedWeakUnion<T>::isStrong() const
|
||||
{
|
||||
return (tp_ & kTAG_MASK) == 0u;
|
||||
return (tp_ & kTagMask) == 0u;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool
|
||||
SharedWeakUnion<T>::isWeak() const
|
||||
{
|
||||
return (tp_ & kTAG_MASK) != 0u;
|
||||
return (tp_ & kTagMask) != 0u;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
@@ -641,7 +641,7 @@ template <class T>
|
||||
T*
|
||||
SharedWeakUnion<T>::unsafeGetRawPtr() const
|
||||
{
|
||||
return reinterpret_cast<T*>(tp_ & kPTR_MASK);
|
||||
return reinterpret_cast<T*>(tp_ & kPtrMask);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
@@ -650,7 +650,7 @@ SharedWeakUnion<T>::unsafeSetRawPtr(T* p, RefStrength rs)
|
||||
{
|
||||
tp_ = reinterpret_cast<std::uintptr_t>(p);
|
||||
if (tp_ && rs == RefStrength::Weak)
|
||||
tp_ |= kTAG_MASK;
|
||||
tp_ |= kTagMask;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
|
||||
@@ -98,11 +98,11 @@ private:
|
||||
// enough for strong pointers and 14 bit counts are enough for weak
|
||||
// pointers. Use type aliases to make it easy to switch types.
|
||||
using CountType = std::uint16_t;
|
||||
static constexpr size_t kSTRONG_COUNT_NUM_BITS = sizeof(CountType) * 8;
|
||||
static constexpr size_t kWEAK_COUNT_NUM_BITS = kSTRONG_COUNT_NUM_BITS - 2;
|
||||
static constexpr size_t kStrongCountNumBits = sizeof(CountType) * 8;
|
||||
static constexpr size_t kWeakCountNumBits = kStrongCountNumBits - 2;
|
||||
using FieldType = std::uint32_t;
|
||||
static constexpr size_t kFIELD_TYPE_BITS = sizeof(FieldType) * 8;
|
||||
static constexpr FieldType kONE = 1;
|
||||
static constexpr size_t kFieldTypeBits = sizeof(FieldType) * 8;
|
||||
static constexpr FieldType kOne = 1;
|
||||
|
||||
/** `refCounts` consists of four fields that are treated atomically:
|
||||
|
||||
@@ -137,21 +137,21 @@ private:
|
||||
|
||||
*/
|
||||
|
||||
mutable std::atomic<FieldType> refCounts_{kSTRONG_DELTA};
|
||||
mutable std::atomic<FieldType> refCounts_{kStrongDelta};
|
||||
|
||||
/** Amount to change the strong count when adding or releasing a reference
|
||||
|
||||
Note: The strong count is stored in the low `StrongCountNumBits` bits
|
||||
of refCounts
|
||||
*/
|
||||
static constexpr FieldType kSTRONG_DELTA = 1;
|
||||
static constexpr FieldType kStrongDelta = 1;
|
||||
|
||||
/** Amount to change the weak count when adding or releasing a reference
|
||||
|
||||
Note: The weak count is stored in the high `WeakCountNumBits` bits of
|
||||
refCounts
|
||||
*/
|
||||
static constexpr FieldType kWEAK_DELTA = (kONE << kSTRONG_COUNT_NUM_BITS);
|
||||
static constexpr FieldType kWeakDelta = (kOne << kStrongCountNumBits);
|
||||
|
||||
/** Flag that is set when the partialDestroy function has started running
|
||||
(or is about to start running).
|
||||
@@ -159,34 +159,33 @@ private:
|
||||
See description of the `refCounts` field for a fuller description of
|
||||
this field.
|
||||
*/
|
||||
static constexpr FieldType kPARTIAL_DESTROY_STARTED_MASK = (kONE << (kFIELD_TYPE_BITS - 1));
|
||||
static constexpr FieldType kPartialDestroyStartedMask = (kOne << (kFieldTypeBits - 1));
|
||||
|
||||
/** Flag that is set when the partialDestroy function has finished running
|
||||
|
||||
See description of the `refCounts` field for a fuller description of
|
||||
this field.
|
||||
*/
|
||||
static constexpr FieldType kPARTIAL_DESTROY_FINISHED_MASK = (kONE << (kFIELD_TYPE_BITS - 2));
|
||||
static constexpr FieldType kPartialDestroyFinishedMask = (kOne << (kFieldTypeBits - 2));
|
||||
|
||||
/** Mask that will zero out all the `count` bits and leave the tag bits
|
||||
unchanged.
|
||||
*/
|
||||
static constexpr FieldType kTAG_MASK =
|
||||
kPARTIAL_DESTROY_STARTED_MASK | kPARTIAL_DESTROY_FINISHED_MASK;
|
||||
static constexpr FieldType kTagMask = kPartialDestroyStartedMask | kPartialDestroyFinishedMask;
|
||||
|
||||
/** Mask that will zero out the `tag` bits and leave the count bits
|
||||
unchanged.
|
||||
*/
|
||||
static constexpr FieldType kVALUE_MASK = ~kTAG_MASK;
|
||||
static constexpr FieldType kValueMask = ~kTagMask;
|
||||
|
||||
/** Mask that will zero out everything except the strong count.
|
||||
*/
|
||||
static constexpr FieldType kSTRONG_MASK = ((kONE << kSTRONG_COUNT_NUM_BITS) - 1) & kVALUE_MASK;
|
||||
static constexpr FieldType kStrongMask = ((kOne << kStrongCountNumBits) - 1) & kValueMask;
|
||||
|
||||
/** Mask that will zero out everything except the weak count.
|
||||
*/
|
||||
static constexpr FieldType kWEAK_MASK =
|
||||
(((kONE << kWEAK_COUNT_NUM_BITS) - 1) << kSTRONG_COUNT_NUM_BITS) & kVALUE_MASK;
|
||||
static constexpr FieldType kWeakMask =
|
||||
(((kOne << kWeakCountNumBits) - 1) << kStrongCountNumBits) & kValueMask;
|
||||
|
||||
/** Unpack the count and tag fields from the packed atomic integer form. */
|
||||
struct RefCountPair
|
||||
@@ -211,29 +210,29 @@ private:
|
||||
[[nodiscard]] FieldType
|
||||
combinedValue() const noexcept;
|
||||
|
||||
static constexpr CountType kMAX_STRONG_VALUE =
|
||||
static_cast<CountType>((kONE << kSTRONG_COUNT_NUM_BITS) - 1);
|
||||
static constexpr CountType kMAX_WEAK_VALUE =
|
||||
static_cast<CountType>((kONE << kWEAK_COUNT_NUM_BITS) - 1);
|
||||
static constexpr CountType kMaxStrongValue =
|
||||
static_cast<CountType>((kOne << kStrongCountNumBits) - 1);
|
||||
static constexpr CountType kMaxWeakValue =
|
||||
static_cast<CountType>((kOne << kWeakCountNumBits) - 1);
|
||||
/** Put an extra margin to detect when running up against limits.
|
||||
This is only used in debug code, and is useful if we reduce the
|
||||
number of bits in the strong and weak counts (to 16 and 14 bits).
|
||||
*/
|
||||
static constexpr CountType kCHECK_STRONG_MAX_VALUE = kMAX_STRONG_VALUE - 32;
|
||||
static constexpr CountType kCHECK_WEAK_MAX_VALUE = kMAX_WEAK_VALUE - 32;
|
||||
static constexpr CountType kCheckStrongMaxValue = kMaxStrongValue - 32;
|
||||
static constexpr CountType kCheckWeakMaxValue = kMaxWeakValue - 32;
|
||||
};
|
||||
};
|
||||
|
||||
inline void
|
||||
IntrusiveRefCounts::addStrongRef() const noexcept
|
||||
{
|
||||
refCounts_.fetch_add(kSTRONG_DELTA, std::memory_order_acq_rel);
|
||||
refCounts_.fetch_add(kStrongDelta, std::memory_order_acq_rel);
|
||||
}
|
||||
|
||||
inline void
|
||||
IntrusiveRefCounts::addWeakRef() const noexcept
|
||||
{
|
||||
refCounts_.fetch_add(kWEAK_DELTA, std::memory_order_acq_rel);
|
||||
refCounts_.fetch_add(kWeakDelta, std::memory_order_acq_rel);
|
||||
}
|
||||
|
||||
inline ReleaseStrongRefAction
|
||||
@@ -252,10 +251,10 @@ IntrusiveRefCounts::releaseStrongRef() const
|
||||
{
|
||||
RefCountPair const prevVal{prevIntVal};
|
||||
XRPL_ASSERT(
|
||||
(prevVal.strong >= kSTRONG_DELTA),
|
||||
(prevVal.strong >= kStrongDelta),
|
||||
"xrpl::IntrusiveRefCounts::releaseStrongRef : previous ref "
|
||||
"higher than new");
|
||||
auto nextIntVal = prevIntVal - kSTRONG_DELTA;
|
||||
auto nextIntVal = prevIntVal - kStrongDelta;
|
||||
ReleaseStrongRefAction action = NoOp;
|
||||
if (prevVal.strong == 1)
|
||||
{
|
||||
@@ -265,7 +264,7 @@ IntrusiveRefCounts::releaseStrongRef() const
|
||||
}
|
||||
else
|
||||
{
|
||||
nextIntVal |= kPARTIAL_DESTROY_STARTED_MASK;
|
||||
nextIntVal |= kPartialDestroyStartedMask;
|
||||
action = PartialDestroy;
|
||||
}
|
||||
}
|
||||
@@ -276,7 +275,7 @@ IntrusiveRefCounts::releaseStrongRef() const
|
||||
// count to zero can start a partial destroy, and that can't happen
|
||||
// twice.
|
||||
XRPL_ASSERT(
|
||||
(action == NoOp) || !(prevIntVal & kPARTIAL_DESTROY_STARTED_MASK),
|
||||
(action == NoOp) || !(prevIntVal & kPartialDestroyStartedMask),
|
||||
"xrpl::IntrusiveRefCounts::releaseStrongRef : not in partial "
|
||||
"destroy");
|
||||
return action;
|
||||
@@ -289,8 +288,8 @@ IntrusiveRefCounts::addWeakReleaseStrongRef() const
|
||||
{
|
||||
using enum ReleaseStrongRefAction;
|
||||
|
||||
static_assert(kWEAK_DELTA > kSTRONG_DELTA);
|
||||
auto constexpr kDELTA = kWEAK_DELTA - kSTRONG_DELTA;
|
||||
static_assert(kWeakDelta > kStrongDelta);
|
||||
static constexpr auto kDelta = kWeakDelta - kStrongDelta;
|
||||
auto prevIntVal = refCounts_.load(std::memory_order_acquire);
|
||||
// This loop will almost always run once. The loop is needed to atomically
|
||||
// change the counts and flags (the count could be atomically changed, but
|
||||
@@ -312,7 +311,7 @@ IntrusiveRefCounts::addWeakReleaseStrongRef() const
|
||||
"xrpl::IntrusiveRefCounts::addWeakReleaseStrongRef : not in "
|
||||
"partial destroy");
|
||||
|
||||
auto nextIntVal = prevIntVal + kDELTA;
|
||||
auto nextIntVal = prevIntVal + kDelta;
|
||||
ReleaseStrongRefAction action = NoOp;
|
||||
if (prevVal.strong == 1)
|
||||
{
|
||||
@@ -322,14 +321,14 @@ IntrusiveRefCounts::addWeakReleaseStrongRef() const
|
||||
}
|
||||
else
|
||||
{
|
||||
nextIntVal |= kPARTIAL_DESTROY_STARTED_MASK;
|
||||
nextIntVal |= kPartialDestroyStartedMask;
|
||||
action = PartialDestroy;
|
||||
}
|
||||
}
|
||||
if (refCounts_.compare_exchange_weak(prevIntVal, nextIntVal, std::memory_order_acq_rel))
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
(!(prevIntVal & kPARTIAL_DESTROY_STARTED_MASK)),
|
||||
(!(prevIntVal & kPartialDestroyStartedMask)),
|
||||
"xrpl::IntrusiveRefCounts::addWeakReleaseStrongRef : not "
|
||||
"started partial destroy");
|
||||
return action;
|
||||
@@ -340,7 +339,7 @@ IntrusiveRefCounts::addWeakReleaseStrongRef() const
|
||||
inline ReleaseWeakRefAction
|
||||
IntrusiveRefCounts::releaseWeakRef() const
|
||||
{
|
||||
auto prevIntVal = refCounts_.fetch_sub(kWEAK_DELTA, std::memory_order_acq_rel);
|
||||
auto prevIntVal = refCounts_.fetch_sub(kWeakDelta, std::memory_order_acq_rel);
|
||||
RefCountPair prev = prevIntVal;
|
||||
if (prev.weak == 1 && prev.strong == 0)
|
||||
{
|
||||
@@ -357,7 +356,7 @@ IntrusiveRefCounts::releaseWeakRef() const
|
||||
{
|
||||
// partial destroy MUST finish before running a full destroy (when
|
||||
// using weak pointers)
|
||||
refCounts_.wait(prevIntVal - kWEAK_DELTA, std::memory_order_acquire);
|
||||
refCounts_.wait(prevIntVal - kWeakDelta, std::memory_order_acquire);
|
||||
}
|
||||
return ReleaseWeakRefAction::Destroy;
|
||||
}
|
||||
@@ -376,7 +375,7 @@ IntrusiveRefCounts::checkoutStrongRefFromWeak() const noexcept
|
||||
if (prev.strong == 0u)
|
||||
return false;
|
||||
|
||||
desiredValue = curValue + kSTRONG_DELTA;
|
||||
desiredValue = curValue + kStrongDelta;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -400,23 +399,22 @@ inline IntrusiveRefCounts::~IntrusiveRefCounts() noexcept
|
||||
#ifndef NDEBUG
|
||||
auto v = refCounts_.load(std::memory_order_acquire);
|
||||
XRPL_ASSERT(
|
||||
(!(v & kVALUE_MASK)), "xrpl::IntrusiveRefCounts::~IntrusiveRefCounts : count must be zero");
|
||||
auto t = v & kTAG_MASK;
|
||||
XRPL_ASSERT(
|
||||
(!t || t == kTAG_MASK), "xrpl::IntrusiveRefCounts::~IntrusiveRefCounts : valid tag");
|
||||
(!(v & kValueMask)), "xrpl::IntrusiveRefCounts::~IntrusiveRefCounts : count must be zero");
|
||||
auto t = v & kTagMask;
|
||||
XRPL_ASSERT((!t || t == kTagMask), "xrpl::IntrusiveRefCounts::~IntrusiveRefCounts : valid tag");
|
||||
#endif
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
inline IntrusiveRefCounts::RefCountPair::RefCountPair(IntrusiveRefCounts::FieldType v) noexcept
|
||||
: strong{static_cast<CountType>(v & kSTRONG_MASK)}
|
||||
, weak{static_cast<CountType>((v & kWEAK_MASK) >> kSTRONG_COUNT_NUM_BITS)}
|
||||
, partialDestroyStartedBit{v & kPARTIAL_DESTROY_STARTED_MASK}
|
||||
, partialDestroyFinishedBit{v & kPARTIAL_DESTROY_FINISHED_MASK}
|
||||
: strong{static_cast<CountType>(v & kStrongMask)}
|
||||
, weak{static_cast<CountType>((v & kWeakMask) >> kStrongCountNumBits)}
|
||||
, partialDestroyStartedBit{v & kPartialDestroyStartedMask}
|
||||
, partialDestroyFinishedBit{v & kPartialDestroyFinishedMask}
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
(strong < kCHECK_STRONG_MAX_VALUE && weak < kCHECK_WEAK_MAX_VALUE),
|
||||
(strong < kCheckStrongMaxValue && weak < kCheckWeakMaxValue),
|
||||
"xrpl::IntrusiveRefCounts::RefCountPair(FieldType) : inputs inside "
|
||||
"range");
|
||||
}
|
||||
@@ -427,7 +425,7 @@ inline IntrusiveRefCounts::RefCountPair::RefCountPair(
|
||||
: strong{s}, weak{w}
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
(strong < kCHECK_STRONG_MAX_VALUE && weak < kCHECK_WEAK_MAX_VALUE),
|
||||
(strong < kCheckStrongMaxValue && weak < kCheckWeakMaxValue),
|
||||
"xrpl::IntrusiveRefCounts::RefCountPair(CountType, CountType) : "
|
||||
"inputs inside range");
|
||||
}
|
||||
@@ -436,11 +434,11 @@ inline IntrusiveRefCounts::FieldType
|
||||
IntrusiveRefCounts::RefCountPair::combinedValue() const noexcept
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
(strong < kCHECK_STRONG_MAX_VALUE && weak < kCHECK_WEAK_MAX_VALUE),
|
||||
(strong < kCheckStrongMaxValue && weak < kCheckWeakMaxValue),
|
||||
"xrpl::IntrusiveRefCounts::RefCountPair::combinedValue : inputs "
|
||||
"inside range");
|
||||
return (static_cast<IntrusiveRefCounts::FieldType>(weak)
|
||||
<< IntrusiveRefCounts::kSTRONG_COUNT_NUM_BITS) |
|
||||
<< IntrusiveRefCounts::kStrongCountNumBits) |
|
||||
static_cast<IntrusiveRefCounts::FieldType>(strong) | partialDestroyStartedBit |
|
||||
partialDestroyFinishedBit;
|
||||
}
|
||||
@@ -451,7 +449,7 @@ partialDestructorFinished(T** o)
|
||||
{
|
||||
T& self = **o;
|
||||
IntrusiveRefCounts::RefCountPair const p =
|
||||
self.refCounts_.fetch_or(IntrusiveRefCounts::kPARTIAL_DESTROY_FINISHED_MASK);
|
||||
self.refCounts_.fetch_or(IntrusiveRefCounts::kPartialDestroyFinishedMask);
|
||||
XRPL_ASSERT(
|
||||
(!p.partialDestroyFinishedBit && p.partialDestroyStartedBit && !p.strong),
|
||||
"xrpl::partialDestructorFinished : not a weak ref");
|
||||
|
||||
@@ -55,8 +55,8 @@ template <class = void>
|
||||
boost::thread_specific_ptr<detail::LocalValues>&
|
||||
getLocalValues()
|
||||
{
|
||||
static boost::thread_specific_ptr<detail::LocalValues> kTSP(&detail::LocalValues::cleanup);
|
||||
return kTSP;
|
||||
static boost::thread_specific_ptr<detail::LocalValues> kTsp(&detail::LocalValues::cleanup);
|
||||
return kTsp;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -10,24 +10,11 @@
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
// DEPRECATED use beast::severities::Severity instead
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-use-enum-class)
|
||||
enum LogSeverity {
|
||||
LSInvalid = -1, // used to indicate an invalid severity
|
||||
LSTrace = 0, // Very low-level progress information, details inside
|
||||
// an operation
|
||||
LSDebug = 1, // Function-level progress information, operations
|
||||
LSInfo = 2, // Server-level progress information, major operations
|
||||
LSWarning = 3, // Conditions that warrant human attention, may indicate
|
||||
// a problem
|
||||
LSError = 4, // A condition that indicates a problem
|
||||
LSFatal = 5 // A severe condition that indicates a server problem
|
||||
};
|
||||
|
||||
/** Manages partitions for logging. */
|
||||
class Logs
|
||||
{
|
||||
@@ -39,17 +26,17 @@ private:
|
||||
std::string partition_;
|
||||
|
||||
public:
|
||||
Sink(std::string partition, beast::severities::Severity thresh, Logs& logs);
|
||||
Sink(std::string partition, beast::Severity thresh, Logs& logs);
|
||||
|
||||
Sink(Sink const&) = delete;
|
||||
Sink&
|
||||
operator=(Sink const&) = delete;
|
||||
|
||||
void
|
||||
write(beast::severities::Severity level, std::string const& text) override;
|
||||
write(beast::Severity level, std::string const& text) override;
|
||||
|
||||
void
|
||||
writeAlways(beast::severities::Severity level, std::string const& text) override;
|
||||
writeAlways(beast::Severity level, std::string const& text) override;
|
||||
};
|
||||
|
||||
/** Manages a system file containing logged output.
|
||||
@@ -136,12 +123,12 @@ private:
|
||||
|
||||
std::mutex mutable mutex_;
|
||||
std::map<std::string, std::unique_ptr<beast::Journal::Sink>, boost::beast::iless> sinks_;
|
||||
beast::severities::Severity thresh_;
|
||||
beast::Severity thresh_;
|
||||
File file_;
|
||||
bool silent_ = false;
|
||||
|
||||
public:
|
||||
Logs(beast::severities::Severity level);
|
||||
Logs(beast::Severity level);
|
||||
|
||||
Logs(Logs const&) = delete;
|
||||
Logs&
|
||||
@@ -161,18 +148,18 @@ public:
|
||||
beast::Journal
|
||||
journal(std::string const& name);
|
||||
|
||||
beast::severities::Severity
|
||||
beast::Severity
|
||||
threshold() const;
|
||||
|
||||
void
|
||||
threshold(beast::severities::Severity thresh);
|
||||
threshold(beast::Severity thresh);
|
||||
|
||||
std::vector<std::pair<std::string, std::string>>
|
||||
partitionSeverities() const;
|
||||
|
||||
void
|
||||
write(
|
||||
beast::severities::Severity level,
|
||||
beast::Severity level,
|
||||
std::string const& partition,
|
||||
std::string const& text,
|
||||
bool console);
|
||||
@@ -192,36 +179,25 @@ public:
|
||||
}
|
||||
|
||||
virtual std::unique_ptr<beast::Journal::Sink>
|
||||
makeSink(std::string const& partition, beast::severities::Severity startingLevel);
|
||||
makeSink(std::string const& partition, beast::Severity startingLevel);
|
||||
|
||||
public:
|
||||
static LogSeverity
|
||||
fromSeverity(beast::severities::Severity level);
|
||||
|
||||
static beast::severities::Severity
|
||||
toSeverity(LogSeverity level);
|
||||
|
||||
static std::string
|
||||
toString(LogSeverity s);
|
||||
toString(beast::Severity s);
|
||||
|
||||
static LogSeverity
|
||||
static std::optional<beast::Severity>
|
||||
fromString(std::string const& s);
|
||||
|
||||
private:
|
||||
// Need to be named before converting
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-use-enum-class)
|
||||
enum {
|
||||
// Maximum line length for log messages.
|
||||
// If the message exceeds this length it will be truncated with
|
||||
// ellipses.
|
||||
MaximumMessageCharacters = 12 * 1024
|
||||
};
|
||||
// Maximum line length for log messages.
|
||||
// If the message exceeds this length it will be truncated with ellipses.
|
||||
static constexpr auto kMaximumMessageCharacters = 12 * 1024;
|
||||
|
||||
static void
|
||||
format(
|
||||
std::string& output,
|
||||
std::string const& message,
|
||||
beast::severities::Severity severity,
|
||||
beast::Severity severity,
|
||||
std::string const& partition);
|
||||
};
|
||||
|
||||
|
||||
@@ -214,12 +214,12 @@ class Number
|
||||
|
||||
public:
|
||||
// The range for the exponent when normalized
|
||||
constexpr static int kMIN_EXPONENT = -32768;
|
||||
constexpr static int kMAX_EXPONENT = 32768;
|
||||
static constexpr int kMinExponent = -32768;
|
||||
static constexpr int kMaxExponent = 32768;
|
||||
|
||||
constexpr static internalrep kMAX_REP = std::numeric_limits<rep>::max();
|
||||
static_assert(kMAX_REP == 9'223'372'036'854'775'807);
|
||||
static_assert(-kMAX_REP == std::numeric_limits<rep>::min() + 1);
|
||||
static constexpr internalrep kMaxRep = std::numeric_limits<rep>::max();
|
||||
static_assert(kMaxRep == 9'223'372'036'854'775'807);
|
||||
static_assert(-kMaxRep == std::numeric_limits<rep>::min() + 1);
|
||||
|
||||
// May need to make unchecked private
|
||||
struct Unchecked
|
||||
@@ -409,26 +409,26 @@ public:
|
||||
static internalrep
|
||||
minMantissa()
|
||||
{
|
||||
return kRANGE.get().min;
|
||||
return kRange.get().min;
|
||||
}
|
||||
|
||||
static internalrep
|
||||
maxMantissa()
|
||||
{
|
||||
return kRANGE.get().max;
|
||||
return kRange.get().max;
|
||||
}
|
||||
|
||||
static int
|
||||
mantissaLog()
|
||||
{
|
||||
return kRANGE.get().log;
|
||||
return kRange.get().log;
|
||||
}
|
||||
|
||||
/// oneSmall is needed because the ranges are private
|
||||
constexpr static Number
|
||||
static constexpr Number
|
||||
oneSmall();
|
||||
/// oneLarge is needed because the ranges are private
|
||||
constexpr static Number
|
||||
static constexpr Number
|
||||
oneLarge();
|
||||
|
||||
// And one is needed because it needs to choose between oneSmall and
|
||||
@@ -445,25 +445,25 @@ private:
|
||||
static thread_local RoundingMode mode;
|
||||
// The available ranges for mantissa
|
||||
|
||||
constexpr static MantissaRange kSMALL_RANGE{MantissaRange::MantissaScale::Small};
|
||||
static_assert(isPowerOfTen(kSMALL_RANGE.min));
|
||||
static_assert(kSMALL_RANGE.min == 1'000'000'000'000'000LL);
|
||||
static_assert(kSMALL_RANGE.max == 9'999'999'999'999'999LL);
|
||||
static_assert(kSMALL_RANGE.log == 15);
|
||||
static_assert(kSMALL_RANGE.min < kMAX_REP);
|
||||
static_assert(kSMALL_RANGE.max < kMAX_REP);
|
||||
constexpr static MantissaRange kLARGE_RANGE{MantissaRange::MantissaScale::Large};
|
||||
static_assert(isPowerOfTen(kLARGE_RANGE.min));
|
||||
static_assert(kLARGE_RANGE.min == 1'000'000'000'000'000'000ULL);
|
||||
static_assert(kLARGE_RANGE.max == internalrep(9'999'999'999'999'999'999ULL));
|
||||
static_assert(kLARGE_RANGE.log == 18);
|
||||
static_assert(kLARGE_RANGE.min < kMAX_REP);
|
||||
static_assert(kLARGE_RANGE.max > kMAX_REP);
|
||||
static constexpr MantissaRange kSmallRange{MantissaRange::MantissaScale::Small};
|
||||
static_assert(isPowerOfTen(kSmallRange.min));
|
||||
static_assert(kSmallRange.min == 1'000'000'000'000'000LL);
|
||||
static_assert(kSmallRange.max == 9'999'999'999'999'999LL);
|
||||
static_assert(kSmallRange.log == 15);
|
||||
static_assert(kSmallRange.min < kMaxRep);
|
||||
static_assert(kSmallRange.max < kMaxRep);
|
||||
static constexpr MantissaRange kLargeRange{MantissaRange::MantissaScale::Large};
|
||||
static_assert(isPowerOfTen(kLargeRange.min));
|
||||
static_assert(kLargeRange.min == 1'000'000'000'000'000'000ULL);
|
||||
static_assert(kLargeRange.max == internalrep(9'999'999'999'999'999'999ULL));
|
||||
static_assert(kLargeRange.log == 18);
|
||||
static_assert(kLargeRange.min < kMaxRep);
|
||||
static_assert(kLargeRange.max > kMaxRep);
|
||||
|
||||
// The range for the mantissa when normalized.
|
||||
// Use reference_wrapper to avoid making copies, and prevent accidentally
|
||||
// changing the values inside the range.
|
||||
static thread_local std::reference_wrapper<MantissaRange const> kRANGE;
|
||||
static thread_local std::reference_wrapper<MantissaRange const> kRange;
|
||||
|
||||
void
|
||||
normalize();
|
||||
@@ -471,7 +471,7 @@ private:
|
||||
/** Normalize Number components to an arbitrary range.
|
||||
*
|
||||
* min/maxMantissa are parameters because this function is used by both
|
||||
* normalize(), which reads from kRANGE, and by normalizeToRange,
|
||||
* normalize(), which reads from kRange, and by normalizeToRange,
|
||||
* which is public and can accept an arbitrary range from the caller.
|
||||
*/
|
||||
template <class T>
|
||||
@@ -521,7 +521,7 @@ constexpr Number::Number(internalrep mantissa, int exponent, Unchecked) noexcept
|
||||
{
|
||||
}
|
||||
|
||||
constexpr static Number kNUM_ZERO{};
|
||||
static constexpr Number kNumZero{};
|
||||
|
||||
inline Number::Number(bool negative, internalrep mantissa, int exponent, Normalized)
|
||||
: Number(negative, mantissa, exponent, Unchecked{})
|
||||
@@ -552,10 +552,10 @@ constexpr Number::rep
|
||||
Number::mantissa() const noexcept
|
||||
{
|
||||
auto m = mantissa_;
|
||||
if (m > kMAX_REP)
|
||||
if (m > kMaxRep)
|
||||
{
|
||||
XRPL_ASSERT_PARTS(
|
||||
!isnormal() || (m % 10 == 0 && m / 10 <= kMAX_REP),
|
||||
!isnormal() || (m % 10 == 0 && m / 10 <= kMaxRep),
|
||||
"xrpl::Number::mantissa",
|
||||
"large normalized mantissa has no remainder");
|
||||
m /= 10;
|
||||
@@ -573,10 +573,10 @@ constexpr int
|
||||
Number::exponent() const noexcept
|
||||
{
|
||||
auto e = exponent_;
|
||||
if (mantissa_ > kMAX_REP)
|
||||
if (mantissa_ > kMaxRep)
|
||||
{
|
||||
XRPL_ASSERT_PARTS(
|
||||
!isnormal() || (mantissa_ % 10 == 0 && mantissa_ / 10 <= kMAX_REP),
|
||||
!isnormal() || (mantissa_ % 10 == 0 && mantissa_ / 10 <= kMaxRep),
|
||||
"xrpl::Number::exponent",
|
||||
"large normalized mantissa has no remainder");
|
||||
++e;
|
||||
@@ -671,29 +671,29 @@ operator/(Number const& x, Number const& y)
|
||||
inline Number
|
||||
Number::min() noexcept
|
||||
{
|
||||
return Number{false, kRANGE.get().min, kMIN_EXPONENT, Unchecked{}};
|
||||
return Number{false, kRange.get().min, kMinExponent, Unchecked{}};
|
||||
}
|
||||
|
||||
inline Number
|
||||
Number::max() noexcept
|
||||
{
|
||||
return Number{false, std::min(kRANGE.get().max, kMAX_REP), kMAX_EXPONENT, Unchecked{}};
|
||||
return Number{false, std::min(kRange.get().max, kMaxRep), kMaxExponent, Unchecked{}};
|
||||
}
|
||||
|
||||
inline Number
|
||||
Number::lowest() noexcept
|
||||
{
|
||||
return Number{true, std::min(kRANGE.get().max, kMAX_REP), kMAX_EXPONENT, Unchecked{}};
|
||||
return Number{true, std::min(kRange.get().max, kMaxRep), kMaxExponent, Unchecked{}};
|
||||
}
|
||||
|
||||
inline bool
|
||||
Number::isnormal() const noexcept
|
||||
{
|
||||
MantissaRange const& range = kRANGE;
|
||||
MantissaRange const& range = kRange;
|
||||
auto const absM = mantissa_;
|
||||
return *this == Number{} ||
|
||||
(range.min <= absM && absM <= range.max && (absM <= kMAX_REP || absM % 10 == 0) &&
|
||||
kMIN_EXPONENT <= exponent_ && exponent_ <= kMAX_EXPONENT);
|
||||
(range.min <= absM && absM <= range.max && (absM <= kMaxRep || absM % 10 == 0) &&
|
||||
kMinExponent <= exponent_ && exponent_ <= kMaxExponent);
|
||||
}
|
||||
|
||||
template <Integral64 T>
|
||||
|
||||
@@ -21,12 +21,12 @@ public:
|
||||
}
|
||||
|
||||
[[nodiscard]] uint256 const&
|
||||
asUint256() const
|
||||
asUInt256() const
|
||||
{
|
||||
return hash_;
|
||||
}
|
||||
uint256&
|
||||
asUint256()
|
||||
asUInt256()
|
||||
{
|
||||
return hash_;
|
||||
}
|
||||
@@ -93,7 +93,7 @@ template <>
|
||||
inline std::size_t
|
||||
extract(SHAMapHash const& key)
|
||||
{
|
||||
return *reinterpret_cast<std::size_t const*>(key.asUint256().data());
|
||||
return *reinterpret_cast<std::size_t const*>(key.asUInt256().data());
|
||||
}
|
||||
|
||||
} // namespace xrpl
|
||||
|
||||
@@ -57,10 +57,10 @@ template <class T>
|
||||
std::shared_ptr<T> const&
|
||||
SharedWeakCachePointer<T>::getStrong() const
|
||||
{
|
||||
static std::shared_ptr<T> const kEMPTY;
|
||||
static std::shared_ptr<T> const kEmpty;
|
||||
if (auto p = std::get_if<std::shared_ptr<T>>(&combo_))
|
||||
return *p;
|
||||
return kEMPTY;
|
||||
return kEmpty;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
|
||||
@@ -7,9 +7,11 @@
|
||||
#include <boost/utility/string_view.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <concepts>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
@@ -26,28 +28,39 @@ namespace xrpl {
|
||||
std::string
|
||||
sqlBlobLiteral(Blob const& blob);
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename T>
|
||||
concept SomeChar = std::same_as<std::remove_cvref_t<T>, int8_t> ||
|
||||
std::same_as<std::remove_cvref_t<T>, char> || std::same_as<std::remove_cvref_t<T>, uint8_t>;
|
||||
|
||||
inline constexpr std::array<std::optional<int>, 256> const kDigitLookupTable = []() {
|
||||
std::array<std::optional<int>, 256> t{};
|
||||
|
||||
for (int i = 0; i < 10; ++i)
|
||||
t['0' + i] = i;
|
||||
|
||||
for (int i = 0; i < 6; ++i)
|
||||
{
|
||||
t['A' + i] = 10 + i;
|
||||
t['a' + i] = 10 + i;
|
||||
}
|
||||
|
||||
return t;
|
||||
}();
|
||||
|
||||
inline std::optional<int>
|
||||
hexCharToInt(SomeChar auto hexChar)
|
||||
{
|
||||
return kDigitLookupTable[static_cast<uint8_t>(hexChar)];
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class Iterator>
|
||||
std::optional<Blob>
|
||||
strUnHex(std::size_t strSize, Iterator begin, Iterator end)
|
||||
{
|
||||
static constexpr std::array<int, 256> const kDIGIT_LOOKUP_TABLE = []() {
|
||||
std::array<int, 256> t{};
|
||||
|
||||
for (auto& x : t)
|
||||
x = -1;
|
||||
|
||||
for (int i = 0; i < 10; ++i)
|
||||
t['0' + i] = i;
|
||||
|
||||
for (int i = 0; i < 6; ++i)
|
||||
{
|
||||
t['A' + i] = 10 + i;
|
||||
t['a' + i] = 10 + i;
|
||||
}
|
||||
|
||||
return t;
|
||||
}();
|
||||
|
||||
Blob out;
|
||||
|
||||
out.reserve((strSize + 1) / 2);
|
||||
@@ -56,27 +69,26 @@ strUnHex(std::size_t strSize, Iterator begin, Iterator end)
|
||||
|
||||
if (strSize & 1)
|
||||
{
|
||||
int c = kDIGIT_LOOKUP_TABLE[*iter++];
|
||||
|
||||
if (c < 0)
|
||||
auto const c = detail::hexCharToInt(*iter++);
|
||||
if (!c.has_value())
|
||||
return {};
|
||||
|
||||
out.push_back(c);
|
||||
out.push_back(static_cast<unsigned char>(*c));
|
||||
}
|
||||
|
||||
while (iter != end)
|
||||
{
|
||||
int const cHigh = kDIGIT_LOOKUP_TABLE[*iter++];
|
||||
auto const cHigh = detail::hexCharToInt(*iter++);
|
||||
|
||||
if (cHigh < 0)
|
||||
if (!cHigh.has_value())
|
||||
return {};
|
||||
|
||||
int const cLow = kDIGIT_LOOKUP_TABLE[*iter++];
|
||||
auto const cLow = detail::hexCharToInt(*iter++);
|
||||
|
||||
if (cLow < 0)
|
||||
if (!cLow.has_value())
|
||||
return {};
|
||||
|
||||
out.push_back(static_cast<unsigned char>((cHigh << 4) | cLow));
|
||||
out.push_back(static_cast<unsigned char>((*cHigh << 4) | *cLow));
|
||||
}
|
||||
|
||||
return {std::move(out)};
|
||||
@@ -120,7 +132,7 @@ std::string
|
||||
trimWhitespace(std::string str);
|
||||
|
||||
std::optional<std::uint64_t>
|
||||
toUint64(std::string const& s);
|
||||
toUInt64(std::string const& s);
|
||||
|
||||
/** Determines if the given string looks like a TOML-file hosting domain.
|
||||
|
||||
|
||||
@@ -30,8 +30,8 @@ public:
|
||||
now(); // seconds since xrpld program start
|
||||
|
||||
private:
|
||||
static std::atomic<rep> kNOW;
|
||||
static std::atomic<bool> kSTOP;
|
||||
static std::atomic<rep> kNow;
|
||||
static std::atomic<bool> kStop;
|
||||
|
||||
struct UpdateThread : private std::thread
|
||||
{
|
||||
|
||||
@@ -46,6 +46,11 @@ struct IsContiguousContainer<Slice> : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename...>
|
||||
struct AlwaysFalseT : std::bool_constant<false>
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/** Integers of any length that is a multiple of 32-bits
|
||||
@@ -62,18 +67,18 @@ struct IsContiguousContainer<Slice> : std::true_type
|
||||
number of bits.
|
||||
*/
|
||||
template <std::size_t Bits, class Tag = void>
|
||||
class BaseUint
|
||||
class BaseUInt
|
||||
{
|
||||
static_assert((Bits % 32) == 0, "The length of a base_uint in bits must be a multiple of 32.");
|
||||
|
||||
static_assert(Bits >= 64, "The length of a base_uint in bits must be at least 64.");
|
||||
|
||||
static constexpr std::size_t kWIDTH = Bits / 32;
|
||||
static constexpr std::size_t kWidth = Bits / 32;
|
||||
|
||||
// This is really big-endian in byte order.
|
||||
// We sometimes use std::uint32_t for speed.
|
||||
|
||||
std::array<std::uint32_t, kWIDTH> data_;
|
||||
std::array<std::uint32_t, kWidth> data_;
|
||||
|
||||
public:
|
||||
//--------------------------------------------------------------------------
|
||||
@@ -81,8 +86,8 @@ public:
|
||||
// STL Container Interface
|
||||
//
|
||||
|
||||
static std::size_t constexpr kBYTES = Bits / 8;
|
||||
static_assert(sizeof(data_) == kBYTES, "");
|
||||
static constexpr std::size_t kBytes = Bits / 8;
|
||||
static_assert(sizeof(data_) == kBytes, "");
|
||||
|
||||
using size_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
@@ -116,7 +121,7 @@ public:
|
||||
iterator
|
||||
end()
|
||||
{
|
||||
return data() + kBYTES;
|
||||
return data() + kBytes;
|
||||
}
|
||||
[[nodiscard]] const_iterator
|
||||
begin() const
|
||||
@@ -126,7 +131,7 @@ public:
|
||||
[[nodiscard]] const_iterator
|
||||
end() const
|
||||
{
|
||||
return data() + kBYTES;
|
||||
return data() + kBytes;
|
||||
}
|
||||
[[nodiscard]] const_iterator
|
||||
cbegin() const
|
||||
@@ -136,7 +141,7 @@ public:
|
||||
[[nodiscard]] const_iterator
|
||||
cend() const
|
||||
{
|
||||
return data() + kBYTES;
|
||||
return data() + kBytes;
|
||||
}
|
||||
|
||||
/** Value hashing function.
|
||||
@@ -160,9 +165,9 @@ private:
|
||||
explicit VoidHelper() = default;
|
||||
};
|
||||
|
||||
explicit BaseUint(void const* data, VoidHelper)
|
||||
explicit BaseUInt(void const* data, VoidHelper)
|
||||
{
|
||||
memcpy(data_.data(), data, kBYTES);
|
||||
memcpy(data_.data(), data, kBytes);
|
||||
}
|
||||
|
||||
// Helper function to initialize a base_uint from a std::string_view.
|
||||
@@ -244,15 +249,15 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
constexpr BaseUint() : data_{}
|
||||
constexpr BaseUInt() : data_{}
|
||||
{
|
||||
}
|
||||
|
||||
constexpr BaseUint(beast::Zero) : data_{}
|
||||
constexpr BaseUInt(beast::Zero) : data_{}
|
||||
{
|
||||
}
|
||||
|
||||
explicit BaseUint(std::uint64_t b)
|
||||
explicit BaseUInt(std::uint64_t b)
|
||||
{
|
||||
*this = b;
|
||||
}
|
||||
@@ -260,7 +265,7 @@ public:
|
||||
// This constructor is intended to be used at compile time since it might
|
||||
// throw at runtime. Consider declaring this constructor consteval once
|
||||
// we get to C++23.
|
||||
explicit constexpr BaseUint(std::string_view sv) noexcept(false)
|
||||
explicit constexpr BaseUInt(std::string_view sv) noexcept(false)
|
||||
: data_(parseFromStringViewThrows(sv))
|
||||
{
|
||||
}
|
||||
@@ -270,24 +275,42 @@ public:
|
||||
class = std::enable_if_t<
|
||||
detail::IsContiguousContainer<Container>::value &&
|
||||
std::is_trivially_copyable_v<typename Container::value_type>>>
|
||||
explicit BaseUint(Container const& c)
|
||||
explicit BaseUInt(Container const& c)
|
||||
{
|
||||
// Use AlwaysFalseT so the static_assert condition is dependent
|
||||
// and only triggers when this constructor template is instantiated.
|
||||
static_assert(
|
||||
detail::AlwaysFalseT<Container>::value,
|
||||
"This constructor is not intended to be used and will be soon removed. "
|
||||
"Use base_uint::fromRaw instead.");
|
||||
}
|
||||
|
||||
template <
|
||||
class Container,
|
||||
class = std::enable_if_t<
|
||||
detail::IsContiguousContainer<Container>::value &&
|
||||
std::is_trivially_copyable_v<typename Container::value_type>>>
|
||||
static BaseUInt
|
||||
fromRaw(Container const& c)
|
||||
{
|
||||
BaseUInt result;
|
||||
XRPL_ASSERT(
|
||||
c.size() * sizeof(typename Container::value_type) == size(),
|
||||
"xrpl::base_uint::base_uint(Container auto) : input size match");
|
||||
std::memcpy(data_.data(), c.data(), size());
|
||||
"xrpl::BaseUInt::fromRaw(Container auto) : input size match");
|
||||
std::memcpy(result.data_.data(), c.data(), size());
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class Container>
|
||||
std::enable_if_t<
|
||||
detail::IsContiguousContainer<Container>::value &&
|
||||
std::is_trivially_copyable_v<typename Container::value_type>,
|
||||
BaseUint&>
|
||||
BaseUInt&>
|
||||
operator=(Container const& c)
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
c.size() * sizeof(typename Container::value_type) == size(),
|
||||
"xrpl::base_uint::operator=(Container auto) : input size match");
|
||||
"xrpl::BaseUInt::operator=(Container auto) : input size match");
|
||||
std::memcpy(data_.data(), c.data(), size());
|
||||
return *this;
|
||||
}
|
||||
@@ -295,14 +318,14 @@ public:
|
||||
/* Construct from a raw pointer.
|
||||
The buffer pointed to by `data` must be at least Bits/8 bytes.
|
||||
*/
|
||||
static BaseUint
|
||||
static BaseUInt
|
||||
fromVoid(void const* data)
|
||||
{
|
||||
return BaseUint(data, VoidHelper());
|
||||
return BaseUInt(data, VoidHelper());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static std::optional<BaseUint>
|
||||
static std::optional<BaseUInt>
|
||||
fromVoidChecked(T const& from)
|
||||
{
|
||||
if (from.size() != size())
|
||||
@@ -313,7 +336,7 @@ public:
|
||||
[[nodiscard]] constexpr int
|
||||
signum() const
|
||||
{
|
||||
for (int i = 0; i < kWIDTH; i++)
|
||||
for (int i = 0; i < kWidth; i++)
|
||||
{
|
||||
if (data_[i] != 0)
|
||||
return 1;
|
||||
@@ -325,24 +348,24 @@ public:
|
||||
bool
|
||||
operator!() const
|
||||
{
|
||||
return *this == beast::kZERO;
|
||||
return *this == beast::kZero;
|
||||
}
|
||||
|
||||
constexpr BaseUint
|
||||
constexpr BaseUInt
|
||||
operator~() const
|
||||
{
|
||||
BaseUint ret;
|
||||
BaseUInt ret;
|
||||
|
||||
for (int i = 0; i < kWIDTH; i++)
|
||||
for (int i = 0; i < kWidth; i++)
|
||||
ret.data_[i] = ~data_[i];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BaseUint&
|
||||
BaseUInt&
|
||||
operator=(std::uint64_t uHost)
|
||||
{
|
||||
*this = beast::kZERO;
|
||||
*this = beast::kZero;
|
||||
// NOLINTBEGIN(cppcoreguidelines-pro-type-member-init)
|
||||
union
|
||||
{
|
||||
@@ -352,43 +375,43 @@ public:
|
||||
// NOLINTEND(cppcoreguidelines-pro-type-member-init)
|
||||
// Put in least significant bits.
|
||||
ul = boost::endian::native_to_big(uHost);
|
||||
data_[kWIDTH - 2] = u[0];
|
||||
data_[kWIDTH - 1] = u[1];
|
||||
data_[kWidth - 2] = u[0];
|
||||
data_[kWidth - 1] = u[1];
|
||||
return *this;
|
||||
}
|
||||
|
||||
BaseUint&
|
||||
operator^=(BaseUint const& b)
|
||||
BaseUInt&
|
||||
operator^=(BaseUInt const& b)
|
||||
{
|
||||
for (int i = 0; i < kWIDTH; i++)
|
||||
for (int i = 0; i < kWidth; i++)
|
||||
data_[i] ^= b.data_[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
BaseUint&
|
||||
operator&=(BaseUint const& b)
|
||||
BaseUInt&
|
||||
operator&=(BaseUInt const& b)
|
||||
{
|
||||
for (int i = 0; i < kWIDTH; i++)
|
||||
for (int i = 0; i < kWidth; i++)
|
||||
data_[i] &= b.data_[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
BaseUint&
|
||||
operator|=(BaseUint const& b)
|
||||
BaseUInt&
|
||||
operator|=(BaseUInt const& b)
|
||||
{
|
||||
for (int i = 0; i < kWIDTH; i++)
|
||||
for (int i = 0; i < kWidth; i++)
|
||||
data_[i] |= b.data_[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
BaseUint&
|
||||
BaseUInt&
|
||||
operator++()
|
||||
{
|
||||
// prefix operator
|
||||
for (int i = kWIDTH - 1; i >= 0; --i)
|
||||
for (int i = kWidth - 1; i >= 0; --i)
|
||||
{
|
||||
data_[i] = boost::endian::native_to_big(boost::endian::big_to_native(data_[i]) + 1);
|
||||
if (data_[i] != 0)
|
||||
@@ -398,20 +421,20 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
BaseUint
|
||||
BaseUInt
|
||||
operator++(int)
|
||||
{
|
||||
// postfix operator
|
||||
BaseUint const ret = *this;
|
||||
BaseUInt const ret = *this;
|
||||
++(*this);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BaseUint&
|
||||
BaseUInt&
|
||||
operator--()
|
||||
{
|
||||
for (int i = kWIDTH - 1; i >= 0; --i)
|
||||
for (int i = kWidth - 1; i >= 0; --i)
|
||||
{
|
||||
auto prev = data_[i];
|
||||
data_[i] = boost::endian::native_to_big(boost::endian::big_to_native(data_[i]) - 1);
|
||||
@@ -423,36 +446,36 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
BaseUint
|
||||
BaseUInt
|
||||
operator--(int)
|
||||
{
|
||||
// postfix operator
|
||||
BaseUint const ret = *this;
|
||||
BaseUInt const ret = *this;
|
||||
--(*this);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
[[nodiscard]] BaseUint
|
||||
[[nodiscard]] BaseUInt
|
||||
next() const
|
||||
{
|
||||
auto ret = *this;
|
||||
return ++ret;
|
||||
}
|
||||
|
||||
[[nodiscard]] BaseUint
|
||||
[[nodiscard]] BaseUInt
|
||||
prev() const
|
||||
{
|
||||
auto ret = *this;
|
||||
return --ret;
|
||||
}
|
||||
|
||||
BaseUint&
|
||||
operator+=(BaseUint const& b)
|
||||
BaseUInt&
|
||||
operator+=(BaseUInt const& b)
|
||||
{
|
||||
std::uint64_t carry = 0;
|
||||
|
||||
for (int i = kWIDTH - 1; i >= 0; i--)
|
||||
for (int i = kWidth - 1; i >= 0; i--)
|
||||
{
|
||||
std::uint64_t const n = carry + boost::endian::big_to_native(data_[i]) +
|
||||
boost::endian::big_to_native(b.data_[i]);
|
||||
@@ -466,7 +489,7 @@ public:
|
||||
|
||||
template <class Hasher>
|
||||
friend void
|
||||
hash_append(Hasher& h, BaseUint const& a) noexcept
|
||||
hash_append(Hasher& h, BaseUInt const& a) noexcept
|
||||
{
|
||||
// Do not allow any endian transformations on this memory
|
||||
h(a.data_.data(), sizeof(a.data_));
|
||||
@@ -503,13 +526,13 @@ public:
|
||||
return parseHex(std::string_view{str});
|
||||
}
|
||||
|
||||
constexpr static std::size_t
|
||||
static constexpr std::size_t
|
||||
size()
|
||||
{
|
||||
return kBYTES;
|
||||
return kBytes;
|
||||
}
|
||||
|
||||
BaseUint<Bits, Tag>&
|
||||
BaseUInt<Bits, Tag>&
|
||||
operator=(beast::Zero)
|
||||
{
|
||||
data_.fill(0);
|
||||
@@ -520,28 +543,28 @@ public:
|
||||
[[nodiscard]] bool
|
||||
isZero() const
|
||||
{
|
||||
return *this == beast::kZERO;
|
||||
return *this == beast::kZero;
|
||||
}
|
||||
[[nodiscard]] bool
|
||||
isNonZero() const
|
||||
{
|
||||
return *this != beast::kZERO;
|
||||
return *this != beast::kZero;
|
||||
}
|
||||
void
|
||||
zero()
|
||||
{
|
||||
*this = beast::kZERO;
|
||||
*this = beast::kZero;
|
||||
}
|
||||
};
|
||||
|
||||
using uint128 = BaseUint<128>;
|
||||
using uint160 = BaseUint<160>;
|
||||
using uint256 = BaseUint<256>;
|
||||
using uint192 = BaseUint<192>;
|
||||
using uint128 = BaseUInt<128>;
|
||||
using uint160 = BaseUInt<160>;
|
||||
using uint256 = BaseUInt<256>;
|
||||
using uint192 = BaseUInt<192>;
|
||||
|
||||
template <std::size_t Bits, class Tag>
|
||||
[[nodiscard]] constexpr std::strong_ordering
|
||||
operator<=>(BaseUint<Bits, Tag> const& lhs, BaseUint<Bits, Tag> const& rhs)
|
||||
operator<=>(BaseUInt<Bits, Tag> const& lhs, BaseUInt<Bits, Tag> const& rhs)
|
||||
{
|
||||
// This comparison might seem wrong on a casual inspection because it
|
||||
// compares data internally stored as std::uint32_t byte-by-byte. But
|
||||
@@ -562,7 +585,7 @@ operator<=>(BaseUint<Bits, Tag> const& lhs, BaseUint<Bits, Tag> const& rhs)
|
||||
|
||||
template <std::size_t Bits, typename Tag>
|
||||
[[nodiscard]] constexpr bool
|
||||
operator==(BaseUint<Bits, Tag> const& lhs, BaseUint<Bits, Tag> const& rhs)
|
||||
operator==(BaseUInt<Bits, Tag> const& lhs, BaseUInt<Bits, Tag> const& rhs)
|
||||
{
|
||||
return (lhs <=> rhs) == 0;
|
||||
}
|
||||
@@ -570,59 +593,59 @@ operator==(BaseUint<Bits, Tag> const& lhs, BaseUint<Bits, Tag> const& rhs)
|
||||
//------------------------------------------------------------------------------
|
||||
template <std::size_t Bits, class Tag>
|
||||
constexpr bool
|
||||
operator==(BaseUint<Bits, Tag> const& a, std::uint64_t b)
|
||||
operator==(BaseUInt<Bits, Tag> const& a, std::uint64_t b)
|
||||
{
|
||||
return a == BaseUint<Bits, Tag>(b);
|
||||
return a == BaseUInt<Bits, Tag>(b);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
template <std::size_t Bits, class Tag>
|
||||
constexpr BaseUint<Bits, Tag>
|
||||
operator^(BaseUint<Bits, Tag> const& a, BaseUint<Bits, Tag> const& b)
|
||||
constexpr BaseUInt<Bits, Tag>
|
||||
operator^(BaseUInt<Bits, Tag> const& a, BaseUInt<Bits, Tag> const& b)
|
||||
{
|
||||
return BaseUint<Bits, Tag>(a) ^= b;
|
||||
return BaseUInt<Bits, Tag>(a) ^= b;
|
||||
}
|
||||
|
||||
template <std::size_t Bits, class Tag>
|
||||
constexpr BaseUint<Bits, Tag>
|
||||
operator&(BaseUint<Bits, Tag> const& a, BaseUint<Bits, Tag> const& b)
|
||||
constexpr BaseUInt<Bits, Tag>
|
||||
operator&(BaseUInt<Bits, Tag> const& a, BaseUInt<Bits, Tag> const& b)
|
||||
{
|
||||
return BaseUint<Bits, Tag>(a) &= b;
|
||||
return BaseUInt<Bits, Tag>(a) &= b;
|
||||
}
|
||||
|
||||
template <std::size_t Bits, class Tag>
|
||||
constexpr BaseUint<Bits, Tag>
|
||||
operator|(BaseUint<Bits, Tag> const& a, BaseUint<Bits, Tag> const& b)
|
||||
constexpr BaseUInt<Bits, Tag>
|
||||
operator|(BaseUInt<Bits, Tag> const& a, BaseUInt<Bits, Tag> const& b)
|
||||
{
|
||||
return BaseUint<Bits, Tag>(a) |= b;
|
||||
return BaseUInt<Bits, Tag>(a) |= b;
|
||||
}
|
||||
|
||||
template <std::size_t Bits, class Tag>
|
||||
constexpr BaseUint<Bits, Tag>
|
||||
operator+(BaseUint<Bits, Tag> const& a, BaseUint<Bits, Tag> const& b)
|
||||
constexpr BaseUInt<Bits, Tag>
|
||||
operator+(BaseUInt<Bits, Tag> const& a, BaseUInt<Bits, Tag> const& b)
|
||||
{
|
||||
return BaseUint<Bits, Tag>(a) += b;
|
||||
return BaseUInt<Bits, Tag>(a) += b;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
template <std::size_t Bits, class Tag>
|
||||
inline std::string
|
||||
to_string(BaseUint<Bits, Tag> const& a)
|
||||
to_string(BaseUInt<Bits, Tag> const& a)
|
||||
{
|
||||
return strHex(a.cbegin(), a.cend());
|
||||
}
|
||||
|
||||
template <std::size_t Bits, class Tag>
|
||||
inline std::string
|
||||
toShortString(BaseUint<Bits, Tag> const& a)
|
||||
toShortString(BaseUInt<Bits, Tag> const& a)
|
||||
{
|
||||
static_assert(BaseUint<Bits, Tag>::kBYTES > 4, "For 4 bytes or less, use a native type");
|
||||
static_assert(BaseUInt<Bits, Tag>::kBytes > 4, "For 4 bytes or less, use a native type");
|
||||
return strHex(a.cbegin(), a.cbegin() + 4) + "...";
|
||||
}
|
||||
|
||||
template <std::size_t Bits, class Tag>
|
||||
inline std::ostream&
|
||||
operator<<(std::ostream& out, BaseUint<Bits, Tag> const& u)
|
||||
operator<<(std::ostream& out, BaseUInt<Bits, Tag> const& u)
|
||||
{
|
||||
return out << to_string(u);
|
||||
}
|
||||
@@ -650,7 +673,7 @@ static_assert(sizeof(uint256) == 256 / 8, "There should be no padding bytes");
|
||||
namespace beast {
|
||||
|
||||
template <std::size_t Bits, class Tag>
|
||||
struct IsUniquelyRepresented<xrpl::BaseUint<Bits, Tag>> : public std::true_type
|
||||
struct IsUniquelyRepresented<xrpl::BaseUInt<Bits, Tag>> : public std::true_type
|
||||
{
|
||||
explicit IsUniquelyRepresented() = default;
|
||||
};
|
||||
|
||||
@@ -30,10 +30,10 @@ using weeks = std::chrono::duration<int, std::ratio_multiply<days::period, std::
|
||||
= seconds(946684800)
|
||||
*/
|
||||
|
||||
constexpr static std::chrono::seconds kEPOCH_OFFSET =
|
||||
static constexpr std::chrono::seconds kEpochOffset =
|
||||
date::sys_days{date::year{2000} / 1 / 1} - date::sys_days{date::year{1970} / 1 / 1};
|
||||
|
||||
static_assert(kEPOCH_OFFSET.count() == 946684800);
|
||||
static_assert(kEpochOffset.count() == 946684800);
|
||||
|
||||
class NetClock
|
||||
{
|
||||
@@ -60,7 +60,7 @@ to_string(NetClock::time_point tp)
|
||||
{
|
||||
// 2000-01-01 00:00:00 UTC is 946684800s from 1970-01-01 00:00:00 UTC
|
||||
using namespace std::chrono;
|
||||
return to_string(system_clock::time_point{tp.time_since_epoch() + kEPOCH_OFFSET});
|
||||
return to_string(system_clock::time_point{tp.time_since_epoch() + kEpochOffset});
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
@@ -77,7 +77,7 @@ toStringIso(NetClock::time_point tp)
|
||||
// 2000-01-01 00:00:00 UTC is 946684800s from 1970-01-01 00:00:00 UTC
|
||||
// Note, NetClock::duration is seconds, as checked by static_assert
|
||||
static_assert(std::is_same_v<NetClock::duration::period, std::ratio<1>>);
|
||||
return toStringIso(date::sys_time<NetClock::duration>{tp.time_since_epoch() + kEPOCH_OFFSET});
|
||||
return toStringIso(date::sys_time<NetClock::duration>{tp.time_since_epoch() + kEpochOffset});
|
||||
}
|
||||
|
||||
/** A clock for measuring elapsed time.
|
||||
|
||||
@@ -31,9 +31,9 @@ makeSeedPair() noexcept
|
||||
// state_t(state_t const&) = delete;
|
||||
// state_t& operator=(state_t const&) = delete;
|
||||
};
|
||||
static StateT kSTATE;
|
||||
std::scoped_lock const lock(kSTATE.mutex);
|
||||
return {kSTATE.dist(kSTATE.gen), kSTATE.dist(kSTATE.gen)};
|
||||
static StateT kState;
|
||||
std::scoped_lock const lock(kState.mutex);
|
||||
return {kState.dist(kState.gen), kState.dist(kState.gen)};
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <optional>
|
||||
|
||||
namespace xrpl {
|
||||
auto constexpr kMULDIV_MAX = std::numeric_limits<std::uint64_t>::max();
|
||||
constexpr auto kMuldivMax = std::numeric_limits<std::uint64_t>::max();
|
||||
|
||||
/** Return value*mul/div accurately.
|
||||
Computes the result of the multiplication and division in
|
||||
|
||||
@@ -236,7 +236,7 @@ public:
|
||||
map_.resize(partitions_);
|
||||
XRPL_ASSERT(
|
||||
partitions_,
|
||||
"xrpl::partitioned_unordered_map::partitioned_unordered_map : "
|
||||
"xrpl::PartitionedUnorderedMap::PartitionedUnorderedMap : "
|
||||
"nonzero partitions");
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ inline beast::xor_shift_engine&
|
||||
defaultPrng()
|
||||
{
|
||||
// This is used to seed the thread-specific PRNGs on demand
|
||||
static beast::xor_shift_engine kSEEDER = [] {
|
||||
static beast::xor_shift_engine kSeeder = [] {
|
||||
std::random_device rng;
|
||||
std::uniform_int_distribution<std::uint64_t> distribution{1};
|
||||
return beast::xor_shift_engine(distribution(rng));
|
||||
@@ -57,17 +57,17 @@ defaultPrng()
|
||||
static std::mutex kM;
|
||||
|
||||
// The thread-specific PRNGs:
|
||||
thread_local beast::xor_shift_engine kENGINE = [] {
|
||||
thread_local beast::xor_shift_engine kEngine = [] {
|
||||
std::uint64_t seed = 0;
|
||||
{
|
||||
std::scoped_lock const lk(kM);
|
||||
std::uniform_int_distribution<std::uint64_t> distribution{1};
|
||||
seed = distribution(kSEEDER);
|
||||
seed = distribution(kSeeder);
|
||||
}
|
||||
return beast::xor_shift_engine{seed};
|
||||
}();
|
||||
|
||||
return kENGINE;
|
||||
return kEngine;
|
||||
}
|
||||
|
||||
/** Return a uniformly distributed random integer.
|
||||
@@ -94,7 +94,7 @@ template <class Engine, class Integral>
|
||||
std::enable_if_t<std::is_integral_v<Integral> && detail::is_engine<Engine>::value, Integral>
|
||||
randInt(Engine& engine, Integral min, Integral max)
|
||||
{
|
||||
XRPL_ASSERT(max > min, "xrpl::rand_int : max over min inputs");
|
||||
XRPL_ASSERT(max > min, "xrpl::randInt : 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
|
||||
|
||||
@@ -22,9 +22,9 @@ safeCast(Src s) noexcept
|
||||
{
|
||||
static_assert(
|
||||
std::is_signed_v<Dest> || std::is_unsigned_v<Src>, "Cannot cast signed to unsigned");
|
||||
constexpr unsigned kNOT_SAME = std::is_signed_v<Dest> != std::is_signed_v<Src>;
|
||||
constexpr unsigned kNotSame = std::is_signed_v<Dest> != std::is_signed_v<Src>;
|
||||
static_assert(
|
||||
sizeof(Dest) >= sizeof(Src) + kNOT_SAME,
|
||||
sizeof(Dest) >= sizeof(Src) + kNotSame,
|
||||
"Destination is too small to hold all values of source");
|
||||
return static_cast<Dest>(s);
|
||||
}
|
||||
@@ -81,7 +81,7 @@ safeDowncast(Src* s) noexcept
|
||||
return static_cast<Dest>(s); // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast)
|
||||
#else
|
||||
auto* result = dynamic_cast<Dest>(s);
|
||||
XRPL_ASSERT(result != nullptr, "xrpl::safe_downcast : pointer downcast is valid");
|
||||
XRPL_ASSERT(result != nullptr, "xrpl::safeDowncast : pointer downcast is valid");
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
@@ -94,7 +94,7 @@ safeDowncast(Src& s) noexcept
|
||||
#ifndef NDEBUG
|
||||
XRPL_ASSERT(
|
||||
dynamic_cast<std::add_pointer_t<std::remove_reference_t<Dest>>>(&s) != nullptr,
|
||||
"xrpl::safe_downcast : reference downcast is valid");
|
||||
"xrpl::safeDowncast : reference downcast is valid");
|
||||
#endif
|
||||
return static_cast<Dest>(s); // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast)
|
||||
}
|
||||
|
||||
@@ -205,7 +205,7 @@ class ScopeUnlock
|
||||
public:
|
||||
explicit ScopeUnlock(std::unique_lock<Mutex>& lock) noexcept(true) : plock_(&lock)
|
||||
{
|
||||
XRPL_ASSERT(plock_->owns_lock(), "xrpl::scope_unlock::scope_unlock : mutex must be locked");
|
||||
XRPL_ASSERT(plock_->owns_lock(), "xrpl::ScopeUnlock::ScopeUnlock : mutex must be locked");
|
||||
plock_->unlock();
|
||||
}
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ public:
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
index >= 0 && (mask_ != 0),
|
||||
"xrpl::packed_spinlock::packed_spinlock : valid index and mask");
|
||||
"xrpl::PackedSpinlock::PackedSpinlock : valid index and mask");
|
||||
}
|
||||
|
||||
[[nodiscard]] bool
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace beast {
|
||||
|
||||
/** Measures handler latency on an io_context queue. */
|
||||
template <class Clock>
|
||||
class IoLatencyProbe
|
||||
class IOLatencyProbe
|
||||
{
|
||||
private:
|
||||
using duration = typename Clock::duration;
|
||||
@@ -30,12 +30,12 @@ private:
|
||||
bool cancel_{false};
|
||||
|
||||
public:
|
||||
IoLatencyProbe(duration const& period, boost::asio::io_context& ios)
|
||||
IOLatencyProbe(duration const& period, boost::asio::io_context& ios)
|
||||
: period_(period), ios_(ios), timer_(ios_)
|
||||
{
|
||||
}
|
||||
|
||||
~IoLatencyProbe()
|
||||
~IOLatencyProbe()
|
||||
{
|
||||
std::unique_lock<decltype(mutex_)> lock(mutex_);
|
||||
cancel(lock, true);
|
||||
@@ -85,7 +85,7 @@ public:
|
||||
{
|
||||
std::scoped_lock const lock(mutex_);
|
||||
if (cancel_)
|
||||
throw std::logic_error("io_latency_probe is canceled");
|
||||
throw std::logic_error("IOLatencyProbe is canceled");
|
||||
boost::asio::post(
|
||||
ios_, SampleOp<Handler>(std::forward<Handler>(handler), Clock::now(), false, this));
|
||||
}
|
||||
@@ -100,7 +100,7 @@ public:
|
||||
{
|
||||
std::scoped_lock const lock(mutex_);
|
||||
if (cancel_)
|
||||
throw std::logic_error("io_latency_probe is canceled");
|
||||
throw std::logic_error("IOLatencyProbe is canceled");
|
||||
boost::asio::post(
|
||||
ios_, SampleOp<Handler>(std::forward<Handler>(handler), Clock::now(), true, this));
|
||||
}
|
||||
@@ -140,18 +140,18 @@ private:
|
||||
Handler handler;
|
||||
time_point start;
|
||||
bool repeat;
|
||||
IoLatencyProbe* probe;
|
||||
IOLatencyProbe* probe;
|
||||
|
||||
SampleOp(
|
||||
Handler const& handler,
|
||||
time_point const& start,
|
||||
bool repeat,
|
||||
IoLatencyProbe* probe)
|
||||
IOLatencyProbe* probe)
|
||||
: handler(handler), start(start), repeat(repeat), probe(probe)
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
probe,
|
||||
"beast::io_latency_probe::sample_op::sample_op : non-null "
|
||||
"beast::IOLatencyProbe::SampleOp::SampleOp : non-null "
|
||||
"probe input");
|
||||
probe->addref();
|
||||
}
|
||||
@@ -164,7 +164,7 @@ private:
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
probe,
|
||||
"beast::io_latency_probe::sample_op::sample_op(sample_op&&) : "
|
||||
"beast::IOLatencyProbe::SampleOp::SampleOp(SampleOp&&) : "
|
||||
"non-null probe input");
|
||||
from.probe = nullptr;
|
||||
}
|
||||
|
||||
@@ -83,8 +83,8 @@ template <class Facade, class Clock = Facade>
|
||||
AbstractClock<Facade>&
|
||||
getAbstractClock()
|
||||
{
|
||||
static detail::AbstractClockWrapper<Facade, Clock> kCLOCK;
|
||||
return kCLOCK;
|
||||
static detail::AbstractClockWrapper<Facade, Clock> kClock;
|
||||
return kClock;
|
||||
}
|
||||
|
||||
} // namespace beast
|
||||
|
||||
@@ -1370,7 +1370,7 @@ private:
|
||||
buck_.resize(size() + additional, cont_);
|
||||
XRPL_ASSERT(
|
||||
loadFactor() <= maxLoadFactor(),
|
||||
"beast::detail::AgedUnorderedContainer::maybe_rehash : maximum "
|
||||
"beast::detail::AgedUnorderedContainer::maybeRehash : maximum "
|
||||
"load factor");
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ setCurrentThreadName(std::string_view newThreadName);
|
||||
|
||||
// On Linux, thread names are limited to 16 bytes including the null terminator.
|
||||
// Maximum number of characters is therefore 15.
|
||||
constexpr std::size_t kMAX_THREAD_NAME_LENGTH = 15;
|
||||
constexpr std::size_t kMaxThreadNameLength = 15;
|
||||
|
||||
/** Sets the name of the caller thread with compile-time size checking.
|
||||
@tparam N The size of the string literal including null terminator
|
||||
@@ -34,7 +34,7 @@ template <std::size_t N>
|
||||
void
|
||||
setCurrentThreadName(char const (&newThreadName)[N])
|
||||
{
|
||||
static_assert(N <= kMAX_THREAD_NAME_LENGTH + 1, "Thread name cannot exceed 15 characters");
|
||||
static_assert(N <= kMaxThreadNameLength + 1, "Thread name cannot exceed 15 characters");
|
||||
|
||||
setCurrentThreadName(std::string_view(newThreadName, N - 1));
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ inline void
|
||||
maybeReverseBytes(T& t, Hasher&)
|
||||
{
|
||||
maybeReverseBytes(
|
||||
t, std::integral_constant<bool, Hasher::kENDIAN != boost::endian::order::native>{});
|
||||
t, std::integral_constant<bool, Hasher::kEndian != boost::endian::order::native>{});
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
@@ -154,7 +154,7 @@ struct IsContiguouslyHashable
|
||||
: public std::integral_constant<
|
||||
bool,
|
||||
IsUniquelyRepresented<T>::value &&
|
||||
(sizeof(T) == 1 || HashAlgorithm::kENDIAN == boost::endian::order::native)>
|
||||
(sizeof(T) == 1 || HashAlgorithm::kEndian == boost::endian::order::native)>
|
||||
{
|
||||
explicit IsContiguouslyHashable() = default;
|
||||
};
|
||||
|
||||
@@ -21,9 +21,9 @@ private:
|
||||
static_assert(sizeof(std::size_t) == 8, "requires 64-bit std::size_t");
|
||||
// Have an internal buffer to avoid the streaming API
|
||||
// A 64-byte buffer should to be big enough for us
|
||||
static constexpr std::size_t kINTERNAL_BUFFER_SIZE = 64;
|
||||
static constexpr std::size_t kInternalBufferSize = 64;
|
||||
|
||||
alignas(64) std::array<std::uint8_t, kINTERNAL_BUFFER_SIZE> buffer_{};
|
||||
alignas(64) std::array<std::uint8_t, kInternalBufferSize> buffer_{};
|
||||
std::span<std::uint8_t> readBuffer_;
|
||||
std::span<std::uint8_t> writeBuffer_;
|
||||
|
||||
@@ -102,7 +102,7 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
static constexpr auto const kENDIAN = boost::endian::order::native;
|
||||
static constexpr auto kEndian = boost::endian::order::native;
|
||||
|
||||
Xxhasher(Xxhasher const&) = delete;
|
||||
Xxhasher&
|
||||
|
||||
@@ -62,9 +62,7 @@ private:
|
||||
{
|
||||
using run_time = std::pair<std::string, typename clock_type::duration>;
|
||||
|
||||
// Need to be named before converting
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-use-enum-class)
|
||||
enum { MaxTop = 10 };
|
||||
static constexpr auto kMaxTop = 10;
|
||||
|
||||
std::size_t suites = 0;
|
||||
std::size_t cases = 0;
|
||||
@@ -148,11 +146,11 @@ Reporter<Unused>::Results::add(SuiteResults const& r)
|
||||
});
|
||||
if (iter != top.end())
|
||||
{
|
||||
if (top.size() == MaxTop)
|
||||
if (top.size() == kMaxTop)
|
||||
top.resize(top.size() - 1);
|
||||
top.emplace(iter, r.name, elapsed);
|
||||
}
|
||||
else if (top.size() < MaxTop)
|
||||
else if (top.size() < kMaxTop)
|
||||
{
|
||||
top.emplace_back(r.name, elapsed);
|
||||
}
|
||||
|
||||
@@ -299,8 +299,8 @@ private:
|
||||
static Suite**
|
||||
pThisSuite()
|
||||
{
|
||||
static Suite* kP_TS = nullptr; // NOLINT TODO
|
||||
return &kP_TS;
|
||||
static Suite* kPTs = nullptr; // NOLINT TODO
|
||||
return &kPTs;
|
||||
}
|
||||
|
||||
/** Runs the suite. */
|
||||
|
||||
@@ -2,29 +2,25 @@
|
||||
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <sstream>
|
||||
|
||||
namespace beast {
|
||||
|
||||
/** A namespace for easy access to logging severity values. */
|
||||
namespace severities {
|
||||
/** Severity level / threshold of a Journal message. */
|
||||
// Hundreds of usages via logging macros
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-use-enum-class)
|
||||
enum Severity {
|
||||
KAll = 0,
|
||||
enum class Severity : std::uint8_t {
|
||||
All = 0,
|
||||
|
||||
KTrace = KAll,
|
||||
KDebug = 1,
|
||||
KInfo = 2,
|
||||
KWarning = 3,
|
||||
KError = 4,
|
||||
KFatal = 5,
|
||||
Trace = All,
|
||||
Debug = 1,
|
||||
Info = 2,
|
||||
Warning = 3,
|
||||
Error = 4,
|
||||
Fatal = 5,
|
||||
|
||||
KDisabled = 6,
|
||||
KNone = KDisabled
|
||||
Disabled = 6,
|
||||
None = Disabled
|
||||
};
|
||||
} // namespace severities
|
||||
|
||||
/** A generic endpoint for log messages.
|
||||
|
||||
@@ -44,9 +40,6 @@ public:
|
||||
class Sink;
|
||||
|
||||
private:
|
||||
// Severity level / threshold of a Journal message.
|
||||
using Severity = severities::Severity;
|
||||
|
||||
// Invariant: sink_ always points to a valid Sink
|
||||
Sink* sink_;
|
||||
|
||||
@@ -183,7 +176,7 @@ public:
|
||||
{
|
||||
public:
|
||||
/** Create a stream which produces no output. */
|
||||
explicit Stream() : sink_(getNullSink()), level_(severities::KDisabled)
|
||||
explicit Stream() : sink_(getNullSink()), level_(Severity::Disabled)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -194,7 +187,7 @@ public:
|
||||
Stream(Sink& sink, Severity level) : sink_(sink), level_(level)
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
level_ < severities::KDisabled, "beast::Journal::Stream::Stream : maximum level");
|
||||
level_ < Severity::Disabled, "beast::Journal::Stream::Stream : maximum level");
|
||||
}
|
||||
|
||||
/** Construct or copy another Stream. */
|
||||
@@ -297,37 +290,37 @@ public:
|
||||
[[nodiscard]] Stream
|
||||
trace() const
|
||||
{
|
||||
return {*sink_, severities::KTrace};
|
||||
return {*sink_, Severity::Trace};
|
||||
}
|
||||
|
||||
[[nodiscard]] Stream
|
||||
debug() const
|
||||
{
|
||||
return {*sink_, severities::KDebug};
|
||||
return {*sink_, Severity::Debug};
|
||||
}
|
||||
|
||||
[[nodiscard]] Stream
|
||||
info() const
|
||||
{
|
||||
return {*sink_, severities::KInfo};
|
||||
return {*sink_, Severity::Info};
|
||||
}
|
||||
|
||||
[[nodiscard]] Stream
|
||||
warn() const
|
||||
{
|
||||
return {*sink_, severities::KWarning};
|
||||
return {*sink_, Severity::Warning};
|
||||
}
|
||||
|
||||
[[nodiscard]] Stream
|
||||
error() const
|
||||
{
|
||||
return {*sink_, severities::KError};
|
||||
return {*sink_, Severity::Error};
|
||||
}
|
||||
|
||||
[[nodiscard]] Stream
|
||||
fatal() const
|
||||
{
|
||||
return {*sink_, severities::KFatal};
|
||||
return {*sink_, Severity::Fatal};
|
||||
}
|
||||
/** @} */
|
||||
};
|
||||
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
}
|
||||
|
||||
[[nodiscard]] bool
|
||||
active(beast::severities::Severity level) const override
|
||||
active(beast::Severity level) const override
|
||||
{
|
||||
return sink_.active(level);
|
||||
}
|
||||
@@ -53,27 +53,27 @@ public:
|
||||
sink_.console(output);
|
||||
}
|
||||
|
||||
[[nodiscard]] beast::severities::Severity
|
||||
[[nodiscard]] beast::Severity
|
||||
threshold() const override
|
||||
{
|
||||
return sink_.threshold();
|
||||
}
|
||||
|
||||
void
|
||||
threshold(beast::severities::Severity thresh) override
|
||||
threshold(beast::Severity thresh) override
|
||||
{
|
||||
sink_.threshold(thresh);
|
||||
}
|
||||
|
||||
void
|
||||
write(beast::severities::Severity level, std::string const& text) override
|
||||
write(beast::Severity level, std::string const& text) override
|
||||
{
|
||||
using beast::Journal;
|
||||
sink_.write(level, prefix_ + text);
|
||||
}
|
||||
|
||||
void
|
||||
writeAlways(severities::Severity level, std::string const& text) override
|
||||
writeAlways(Severity level, std::string const& text) override
|
||||
{
|
||||
using beast::Journal;
|
||||
sink_.writeAlways(level, prefix_ + text);
|
||||
|
||||
@@ -27,7 +27,7 @@ struct Zero
|
||||
};
|
||||
|
||||
namespace {
|
||||
constexpr Zero kZERO{};
|
||||
constexpr Zero kZero{};
|
||||
} // namespace
|
||||
|
||||
/** Default implementation of signum calls the method on the class. */
|
||||
@@ -102,42 +102,42 @@ template <typename T>
|
||||
bool
|
||||
operator==(Zero, T const& t)
|
||||
{
|
||||
return t == kZERO;
|
||||
return t == kZero;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool
|
||||
operator!=(Zero, T const& t)
|
||||
{
|
||||
return t != kZERO;
|
||||
return t != kZero;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool
|
||||
operator<(Zero, T const& t)
|
||||
{
|
||||
return t > kZERO;
|
||||
return t > kZero;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool
|
||||
operator>(Zero, T const& t)
|
||||
{
|
||||
return t < kZERO;
|
||||
return t < kZero;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool
|
||||
operator>=(Zero, T const& t)
|
||||
{
|
||||
return t <= kZERO;
|
||||
return t <= kZero;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool
|
||||
operator<=(Zero, T const& t)
|
||||
{
|
||||
return t >= kZERO;
|
||||
return t >= kZero;
|
||||
}
|
||||
|
||||
} // namespace beast
|
||||
|
||||
@@ -14,23 +14,23 @@ void
|
||||
rngfill(void* const buffer, std::size_t const bytes, Generator& g)
|
||||
{
|
||||
using result_type = typename Generator::result_type;
|
||||
constexpr std::size_t kRESULT_SIZE = sizeof(result_type);
|
||||
constexpr std::size_t kResultSize = sizeof(result_type);
|
||||
|
||||
std::uint8_t* const bufferStart = static_cast<std::uint8_t*>(buffer);
|
||||
std::size_t const completeIterations = bytes / kRESULT_SIZE;
|
||||
std::size_t const bytesRemaining = bytes % kRESULT_SIZE;
|
||||
std::size_t const completeIterations = bytes / kResultSize;
|
||||
std::size_t const bytesRemaining = bytes % kResultSize;
|
||||
|
||||
for (std::size_t count = 0; count < completeIterations; ++count)
|
||||
{
|
||||
result_type const v = g();
|
||||
std::size_t const offset = count * kRESULT_SIZE;
|
||||
std::memcpy(bufferStart + offset, &v, kRESULT_SIZE);
|
||||
std::size_t const offset = count * kResultSize;
|
||||
std::memcpy(bufferStart + offset, &v, kResultSize);
|
||||
}
|
||||
|
||||
if (bytesRemaining > 0)
|
||||
{
|
||||
result_type const v = g();
|
||||
std::size_t const offset = completeIterations * kRESULT_SIZE;
|
||||
std::size_t const offset = completeIterations * kResultSize;
|
||||
std::memcpy(bufferStart + offset, &v, bytesRemaining);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,12 +26,14 @@ public:
|
||||
result_type
|
||||
operator()();
|
||||
|
||||
static result_type constexpr min()
|
||||
static constexpr result_type
|
||||
min()
|
||||
{
|
||||
return std::numeric_limits<result_type>::min();
|
||||
}
|
||||
|
||||
static result_type constexpr max()
|
||||
static constexpr result_type
|
||||
max()
|
||||
{
|
||||
return std::numeric_limits<result_type>::max();
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ public:
|
||||
that were previously considered valid to no longer
|
||||
be allowed.
|
||||
*/
|
||||
static constexpr std::size_t kMAX_SERIALIZED_CONDITION = 128;
|
||||
static constexpr std::size_t kMaxSerializedCondition = 128;
|
||||
|
||||
/** Load a condition from its binary form
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ public:
|
||||
that were previously considered valid to no longer
|
||||
be allowed.
|
||||
*/
|
||||
static constexpr std::size_t kMAX_SERIALIZED_FULFILLMENT = 256;
|
||||
static constexpr std::size_t kMaxSerializedFulfillment = 256;
|
||||
|
||||
/** Load a fulfillment from its binary form
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ public:
|
||||
While future versions of this code will never lower
|
||||
this limit, they may opt to raise it.
|
||||
*/
|
||||
static constexpr std::size_t kMAX_PREIMAGE_LENGTH = 128;
|
||||
static constexpr std::size_t kMaxPreimageLength = 128;
|
||||
|
||||
/** Parse the payload for a PreimageSha256 condition
|
||||
|
||||
@@ -65,7 +65,7 @@ public:
|
||||
return {};
|
||||
}
|
||||
|
||||
if (s.size() > kMAX_PREIMAGE_LENGTH)
|
||||
if (s.size() > kMaxPreimageLength)
|
||||
{
|
||||
ec = Error::PreimageTooLong;
|
||||
return {};
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace xrpl {
|
||||
|
||||
/// Coroutine stack size (1.5 MB). Increased from 1 MB because
|
||||
/// ASAN-instrumented deep call stacks exceeded the original limit.
|
||||
constexpr std::size_t kCORO_STACK_SIZE = 1536 * 1024;
|
||||
constexpr std::size_t kCoroStackSize = 1536 * 1024;
|
||||
|
||||
template <class F>
|
||||
JobQueue::Coro::Coro(CoroCreateT, JobQueue& jq, JobType type, std::string name, F&& f)
|
||||
@@ -14,7 +14,7 @@ JobQueue::Coro::Coro(CoroCreateT, JobQueue& jq, JobType type, std::string name,
|
||||
, type_(type)
|
||||
, name_(std::move(name))
|
||||
, coro_(
|
||||
boost::context::protected_fixedsize_stack(kCORO_STACK_SIZE),
|
||||
boost::context::protected_fixedsize_stack(kCoroStackSize),
|
||||
[this, fn = std::forward<F>(f)](boost::coroutines2::coroutine<void>::push_type& doYield) {
|
||||
yield_ = &doYield;
|
||||
yield();
|
||||
|
||||
@@ -101,8 +101,8 @@ public:
|
||||
static JobTypes const&
|
||||
instance()
|
||||
{
|
||||
static JobTypes const kTYPES;
|
||||
return kTYPES;
|
||||
static JobTypes const kTypes;
|
||||
return kTypes;
|
||||
}
|
||||
|
||||
static std::string const&
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
/** A PropertyStream::Sink which produces a json::Value of type objectValue. */
|
||||
/** A PropertyStream::Sink which produces a json::Value of type ValueType::Object. */
|
||||
class JsonPropertyStream : public beast::PropertyStream
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -67,27 +67,25 @@ public:
|
||||
[[nodiscard]] std::string
|
||||
getFormattedErrorMessages() const;
|
||||
|
||||
static constexpr unsigned kNEST_LIMIT{25};
|
||||
static constexpr unsigned kNestLimit{25};
|
||||
|
||||
private:
|
||||
// 53 files, protocol-wide
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-use-enum-class)
|
||||
enum TokenType {
|
||||
TokenEndOfStream = 0,
|
||||
TokenObjectBegin,
|
||||
TokenObjectEnd,
|
||||
TokenArrayBegin,
|
||||
TokenArrayEnd,
|
||||
TokenString,
|
||||
TokenInteger,
|
||||
TokenDouble,
|
||||
TokenTrue,
|
||||
TokenFalse,
|
||||
TokenNull,
|
||||
TokenArraySeparator,
|
||||
TokenMemberSeparator,
|
||||
TokenComment,
|
||||
TokenError
|
||||
enum class TokenType {
|
||||
EndOfStream = 0,
|
||||
ObjectBegin,
|
||||
ObjectEnd,
|
||||
ArrayBegin,
|
||||
ArrayEnd,
|
||||
String,
|
||||
Integer,
|
||||
Double,
|
||||
True,
|
||||
False,
|
||||
Null,
|
||||
ArraySeparator,
|
||||
MemberSeparator,
|
||||
Comment,
|
||||
Error
|
||||
};
|
||||
|
||||
class Token
|
||||
|
||||
@@ -15,22 +15,20 @@ namespace json {
|
||||
|
||||
/** \brief Type of the value held by a Value object.
|
||||
*/
|
||||
// Used throughout JSON layer
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-use-enum-class)
|
||||
enum ValueType {
|
||||
NullValue = 0, ///< 'null' value
|
||||
IntValue, ///< signed integer value
|
||||
UintValue, ///< unsigned integer value
|
||||
RealValue, ///< double value
|
||||
StringValue, ///< UTF-8 string value
|
||||
BooleanValue, ///< bool value
|
||||
ArrayValue, ///< array value (ordered list)
|
||||
ObjectValue ///< object value (collection of name/value pairs).
|
||||
enum class ValueType {
|
||||
Null = 0, ///< 'null' value
|
||||
Int, ///< signed integer value
|
||||
UInt, ///< unsigned integer value
|
||||
Real, ///< double value
|
||||
String, ///< UTF-8 string value
|
||||
Boolean, ///< bool value
|
||||
Array, ///< array value (ordered list)
|
||||
Object ///< object value (collection of name/value pairs).
|
||||
};
|
||||
|
||||
/** \brief Lightweight wrapper to tag static string.
|
||||
*
|
||||
* Value constructor and objectValue member assignment takes advantage of the
|
||||
* Value constructor and ValueType::Object member assignment takes advantage of the
|
||||
* StaticString and avoid the cost of string duplication when storing the
|
||||
* string or the member name.
|
||||
*
|
||||
@@ -104,8 +102,8 @@ operator!=(StaticString x, std::string const& y)
|
||||
/** \brief Represents a <a HREF="http://www.json.org">JSON</a> value.
|
||||
*
|
||||
* This class is a discriminated union wrapper that can represent a:
|
||||
* - signed integer [range: Value::minInt - Value::maxInt]
|
||||
* - unsigned integer (range: 0 - Value::maxUInt)
|
||||
* - signed integer [range: Value::kMinInt - Value::kMaxInt]
|
||||
* - unsigned integer (range: 0 - Value::kMaxUInt)
|
||||
* - double
|
||||
* - UTF-8 string
|
||||
* - boolean
|
||||
@@ -116,16 +114,16 @@ operator!=(StaticString x, std::string const& y)
|
||||
* The type of the held value is represented by a #ValueType and
|
||||
* can be obtained using type().
|
||||
*
|
||||
* values of an #objectValue or #arrayValue can be accessed using operator[]()
|
||||
* methods. Non const methods will automatically create the a #nullValue element
|
||||
* values of an ValueType::Object or ValueType::Array can be accessed using operator[]()
|
||||
* methods. Non const methods will automatically create the a ValueType::Null element
|
||||
* if it does not exist.
|
||||
* The sequence of an #arrayValue will be automatically resize and initialized
|
||||
* with #nullValue. resize() can be used to enlarge or truncate an #arrayValue.
|
||||
* The sequence of an ValueType::Array will be automatically resize and initialized
|
||||
* with ValueType::Null. resize() can be used to enlarge or truncate an ValueType::Array.
|
||||
*
|
||||
* The get() methods can be used to obtain a default value in the case the
|
||||
* required element does not exist.
|
||||
*
|
||||
* It is possible to iterate over the list of a #objectValue values using
|
||||
* It is possible to iterate over the list of a ValueType::Object values using
|
||||
* the getMemberNames() method.
|
||||
*/
|
||||
class Value
|
||||
@@ -140,18 +138,16 @@ public:
|
||||
using Int = json::Int;
|
||||
using ArrayIndex = UInt;
|
||||
|
||||
static Value const kNULL;
|
||||
static constexpr Int kMIN_INT = std::numeric_limits<Int>::min();
|
||||
static constexpr Int kMAX_INT = std::numeric_limits<Int>::max();
|
||||
static constexpr UInt kMAX_U_INT = std::numeric_limits<UInt>::max();
|
||||
static Value const kNull;
|
||||
static constexpr Int kMinInt = std::numeric_limits<Int>::min();
|
||||
static constexpr Int kMaxInt = std::numeric_limits<Int>::max();
|
||||
static constexpr UInt kMaxUInt = std::numeric_limits<UInt>::max();
|
||||
|
||||
private:
|
||||
class CZString
|
||||
{
|
||||
public:
|
||||
// Stored as int field, implicit conversion
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-use-enum-class)
|
||||
enum DuplicationPolicy { NoDuplication = 0, Duplicate, DuplicateOnCopy };
|
||||
enum class DuplicationPolicy { NoDuplication = 0, Duplicate, DuplicateOnCopy };
|
||||
|
||||
CZString(int index);
|
||||
CZString(char const* cstr, DuplicationPolicy allocate);
|
||||
@@ -182,19 +178,19 @@ public:
|
||||
/** \brief Create a default Value of the given type.
|
||||
|
||||
This is a very useful constructor.
|
||||
To create an empty array, pass arrayValue.
|
||||
To create an empty object, pass objectValue.
|
||||
To create an empty array, pass ValueType::Array.
|
||||
To create an empty object, pass ValueType::Object.
|
||||
Another Value can then be set to this one by assignment.
|
||||
This is useful since clear() and resize() will not alter types.
|
||||
|
||||
Examples:
|
||||
\code
|
||||
json::Value null_value; // null
|
||||
json::Value arr_value(json::arrayValue); // []
|
||||
json::Value obj_value(json::objectValue); // {}
|
||||
json::Value arr_value(json::ValueType::Array); // []
|
||||
json::Value obj_value(json::ValueType::Object); // {}
|
||||
\endcode
|
||||
*/
|
||||
Value(ValueType type = NullValue);
|
||||
Value(ValueType type = ValueType::Null);
|
||||
Value(Int value);
|
||||
Value(UInt value);
|
||||
Value(double value);
|
||||
@@ -290,7 +286,7 @@ public:
|
||||
operator bool() const;
|
||||
|
||||
/// Remove all object members and array elements.
|
||||
/// \pre type() is arrayValue, objectValue, or nullValue
|
||||
/// \pre type() is ValueType::Array, ValueType::Object, or ValueType::Null
|
||||
/// \post type() is unchanged
|
||||
void
|
||||
clear();
|
||||
@@ -367,7 +363,7 @@ public:
|
||||
///
|
||||
/// Do nothing if it did not exist.
|
||||
/// \return the removed Value, or null.
|
||||
/// \pre type() is objectValue or nullValue
|
||||
/// \pre type() is ValueType::Object or ValueType::Null
|
||||
/// \post type() is unchanged
|
||||
Value
|
||||
removeMember(char const* key);
|
||||
@@ -388,8 +384,8 @@ public:
|
||||
/// \brief Return a list of the member names.
|
||||
///
|
||||
/// If null, return an empty list.
|
||||
/// \pre type() is objectValue or nullValue
|
||||
/// \post if type() was nullValue, it remains nullValue
|
||||
/// \pre type() is ValueType::Object or ValueType::Null
|
||||
/// \post if type() was ValueType::Null, it remains ValueType::Null
|
||||
[[nodiscard]] Members
|
||||
getMemberNames() const;
|
||||
|
||||
@@ -469,16 +465,14 @@ operator>=(Value const& x, Value const& y)
|
||||
* string value memory management done by Value.
|
||||
*
|
||||
* - makeMemberName() and releaseMemberName() are called to respectively
|
||||
* duplicate and free an json::objectValue member name.
|
||||
* duplicate and free an json::ValueType::Object member name.
|
||||
* - duplicateStringValue() and releaseStringValue() are called similarly to
|
||||
* duplicate and free a json::stringValue value.
|
||||
* duplicate and free a json::ValueType::String value.
|
||||
*/
|
||||
class ValueAllocator
|
||||
{
|
||||
public:
|
||||
// Need to be named before converting
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-use-enum-class)
|
||||
enum { Unknown = (unsigned)-1 };
|
||||
static constexpr auto kUnknown = (unsigned)-1;
|
||||
|
||||
virtual ~ValueAllocator() = default;
|
||||
|
||||
@@ -487,7 +481,7 @@ public:
|
||||
virtual void
|
||||
releaseMemberName(char* memberName) = 0;
|
||||
virtual char*
|
||||
duplicateStringValue(char const* value, unsigned int length = Unknown) = 0;
|
||||
duplicateStringValue(char const* value, unsigned int length = kUnknown) = 0;
|
||||
virtual void
|
||||
releaseStringValue(char* value) = 0;
|
||||
};
|
||||
@@ -523,12 +517,12 @@ public:
|
||||
[[nodiscard]] Value
|
||||
key() const;
|
||||
|
||||
/// Return the index of the referenced Value. -1 if it is not an arrayValue.
|
||||
/// Return the index of the referenced Value. -1 if it is not an ValueType::Array.
|
||||
[[nodiscard]] UInt
|
||||
index() const;
|
||||
|
||||
/// Return the member name of the referenced Value. "" if it is not an
|
||||
/// objectValue.
|
||||
/// ValueType::Object.
|
||||
[[nodiscard]] char const*
|
||||
memberName() const;
|
||||
|
||||
|
||||
@@ -204,31 +204,31 @@ writeValue(Write const& write, Value const& value)
|
||||
{
|
||||
switch (value.type())
|
||||
{
|
||||
case NullValue:
|
||||
case ValueType::Null:
|
||||
write("null", 4);
|
||||
break;
|
||||
|
||||
case IntValue:
|
||||
case ValueType::Int:
|
||||
writeString(write, valueToString(value.asInt()));
|
||||
break;
|
||||
|
||||
case UintValue:
|
||||
case ValueType::UInt:
|
||||
writeString(write, valueToString(value.asUInt()));
|
||||
break;
|
||||
|
||||
case RealValue:
|
||||
case ValueType::Real:
|
||||
writeString(write, valueToString(value.asDouble()));
|
||||
break;
|
||||
|
||||
case StringValue:
|
||||
case ValueType::String:
|
||||
writeString(write, valueToQuotedString(value.asCString()));
|
||||
break;
|
||||
|
||||
case BooleanValue:
|
||||
case ValueType::Boolean:
|
||||
writeString(write, valueToString(value.asBool()));
|
||||
break;
|
||||
|
||||
case ArrayValue: {
|
||||
case ValueType::Array: {
|
||||
write("[", 1);
|
||||
int const size = value.size();
|
||||
for (int index = 0; index < size; ++index)
|
||||
@@ -241,7 +241,7 @@ writeValue(Write const& write, Value const& value)
|
||||
break;
|
||||
}
|
||||
|
||||
case ObjectValue: {
|
||||
case ValueType::Object: {
|
||||
Value::Members const members = value.getMemberNames();
|
||||
write("{", 1);
|
||||
for (auto it = members.begin(); it != members.end(); ++it)
|
||||
|
||||
@@ -67,7 +67,7 @@ public:
|
||||
[[nodiscard]] virtual json::Value
|
||||
getJson(bool isAdmin) const = 0;
|
||||
|
||||
/** Returns a json::objectValue. */
|
||||
/** Returns a json::ValueType::Object. */
|
||||
[[nodiscard]] virtual json::Value
|
||||
getJson(uint256 const& amendment, bool isAdmin) const = 0;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ struct CreateGenesisT
|
||||
{
|
||||
explicit CreateGenesisT() = default;
|
||||
};
|
||||
extern CreateGenesisT const kCREATE_GENESIS;
|
||||
extern CreateGenesisT const kCreateGenesis;
|
||||
|
||||
/** Holds a ledger.
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace xrpl {
|
||||
Values should not be duplicated.
|
||||
@see getNextLedgerTimeResolution
|
||||
*/
|
||||
std::chrono::seconds constexpr kLEDGER_POSSIBLE_TIME_RESOLUTIONS[] = {
|
||||
constexpr std::chrono::seconds kLedgerPossibleTimeResolutions[] = {
|
||||
std::chrono::seconds{10},
|
||||
std::chrono::seconds{20},
|
||||
std::chrono::seconds{30},
|
||||
@@ -21,16 +21,16 @@ std::chrono::seconds constexpr kLEDGER_POSSIBLE_TIME_RESOLUTIONS[] = {
|
||||
std::chrono::seconds{120}};
|
||||
|
||||
//! Initial resolution of ledger close time.
|
||||
auto constexpr kLEDGER_DEFAULT_TIME_RESOLUTION = kLEDGER_POSSIBLE_TIME_RESOLUTIONS[2];
|
||||
constexpr auto kLedgerDefaultTimeResolution = kLedgerPossibleTimeResolutions[2];
|
||||
|
||||
//! Close time resolution in genesis ledger
|
||||
auto constexpr kLEDGER_GENESIS_TIME_RESOLUTION = kLEDGER_POSSIBLE_TIME_RESOLUTIONS[0];
|
||||
constexpr auto kLedgerGenesisTimeResolution = kLedgerPossibleTimeResolutions[0];
|
||||
|
||||
//! How often we increase the close time resolution (in numbers of ledgers)
|
||||
auto constexpr kINCREASE_LEDGER_TIME_RESOLUTION_EVERY = 8;
|
||||
constexpr auto kIncreaseLedgerTimeResolutionEvery = 8;
|
||||
|
||||
//! How often we decrease the close time resolution (in numbers of ledgers)
|
||||
auto constexpr kDECREASE_LEDGER_TIME_RESOLUTION_EVERY = 1;
|
||||
constexpr auto kDecreaseLedgerTimeResolutionEvery = 1;
|
||||
|
||||
/** Calculates the close time resolution for the specified ledger.
|
||||
|
||||
@@ -46,7 +46,7 @@ auto constexpr kDECREASE_LEDGER_TIME_RESOLUTION_EVERY = 1;
|
||||
@param ledgerSeq the sequence number of the new ledger
|
||||
|
||||
@pre previousResolution must be a valid bin
|
||||
from @ref kLEDGER_POSSIBLE_TIME_RESOLUTIONS
|
||||
from @ref kLedgerPossibleTimeResolutions
|
||||
|
||||
@tparam Rep Type representing number of ticks in std::chrono::duration
|
||||
@tparam Period An std::ratio representing tick period in
|
||||
@@ -67,30 +67,30 @@ getNextLedgerTimeResolution(
|
||||
using namespace std::chrono;
|
||||
// Find the current resolution:
|
||||
auto iter = std::find(
|
||||
std::begin(kLEDGER_POSSIBLE_TIME_RESOLUTIONS),
|
||||
std::end(kLEDGER_POSSIBLE_TIME_RESOLUTIONS),
|
||||
std::begin(kLedgerPossibleTimeResolutions),
|
||||
std::end(kLedgerPossibleTimeResolutions),
|
||||
previousResolution);
|
||||
XRPL_ASSERT(
|
||||
iter != std::end(kLEDGER_POSSIBLE_TIME_RESOLUTIONS),
|
||||
iter != std::end(kLedgerPossibleTimeResolutions),
|
||||
"xrpl::getNextLedgerTimeResolution : found time resolution");
|
||||
|
||||
// This should never happen, but just as a precaution
|
||||
if (iter == std::end(kLEDGER_POSSIBLE_TIME_RESOLUTIONS))
|
||||
if (iter == std::end(kLedgerPossibleTimeResolutions))
|
||||
return previousResolution;
|
||||
|
||||
// If we did not previously agree, we try to decrease the resolution to
|
||||
// improve the chance that we will agree now.
|
||||
if (!previousAgree && (ledgerSeq % Seq{kDECREASE_LEDGER_TIME_RESOLUTION_EVERY} == Seq{0}))
|
||||
if (!previousAgree && (ledgerSeq % Seq{kDecreaseLedgerTimeResolutionEvery} == Seq{0}))
|
||||
{
|
||||
if (++iter != std::end(kLEDGER_POSSIBLE_TIME_RESOLUTIONS))
|
||||
if (++iter != std::end(kLedgerPossibleTimeResolutions))
|
||||
return *iter;
|
||||
}
|
||||
|
||||
// If we previously agreed, we try to increase the resolution to determine
|
||||
// if we can continue to agree.
|
||||
if (previousAgree && (ledgerSeq % Seq{kINCREASE_LEDGER_TIME_RESOLUTION_EVERY} == Seq{0}))
|
||||
if (previousAgree && (ledgerSeq % Seq{kIncreaseLedgerTimeResolutionEvery} == Seq{0}))
|
||||
{
|
||||
if (iter-- != std::begin(kLEDGER_POSSIBLE_TIME_RESOLUTIONS))
|
||||
if (iter-- != std::begin(kLedgerPossibleTimeResolutions))
|
||||
return *iter;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace xrpl {
|
||||
inline constexpr struct OpenLedgerT
|
||||
{
|
||||
explicit constexpr OpenLedgerT() = default;
|
||||
} kOPEN_LEDGER{};
|
||||
} kOpenLedger{};
|
||||
|
||||
/** Batch view construction tag.
|
||||
|
||||
@@ -33,7 +33,7 @@ inline constexpr struct OpenLedgerT
|
||||
inline constexpr struct BatchViewT
|
||||
{
|
||||
explicit constexpr BatchViewT() = default;
|
||||
} kBATCH_VIEW{};
|
||||
} kBatchView{};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -47,7 +47,7 @@ private:
|
||||
// Initial size for the monotonic_buffer_resource used for allocations
|
||||
// The size was chosen from the old `qalloc` code (which this replaces).
|
||||
// It is unclear how the size initially chosen in qalloc.
|
||||
static constexpr size_t kINITIAL_BUFFER_SIZE = kilobytes(256);
|
||||
static constexpr size_t kInitialBufferSize = kilobytes(256);
|
||||
|
||||
class TxsIterImpl;
|
||||
|
||||
@@ -139,7 +139,7 @@ public:
|
||||
std::shared_ptr<void const> hold = nullptr);
|
||||
|
||||
OpenView(OpenLedgerT, Rules const& rules, std::shared_ptr<ReadView const> const& base)
|
||||
: OpenView(kOPEN_LEDGER, &*base, rules, base)
|
||||
: OpenView(kOpenLedger, &*base, rules, base)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -19,16 +19,16 @@ public:
|
||||
// Initial size for the monotonic_buffer_resource used for allocations
|
||||
// The size was chosen from the old `qalloc` code (which this replaces).
|
||||
// It is unclear how the size initially chosen in qalloc.
|
||||
static constexpr size_t kINITIAL_BUFFER_SIZE = kilobytes(256);
|
||||
static constexpr size_t kInitialBufferSize = kilobytes(256);
|
||||
|
||||
RawStateTable()
|
||||
: monotonic_resource_{std::make_unique<boost::container::pmr::monotonic_buffer_resource>(
|
||||
kINITIAL_BUFFER_SIZE)}
|
||||
kInitialBufferSize)}
|
||||
, items_{monotonic_resource_.get()} {};
|
||||
|
||||
RawStateTable(RawStateTable const& rhs)
|
||||
: monotonic_resource_{std::make_unique<boost::container::pmr::monotonic_buffer_resource>(
|
||||
kINITIAL_BUFFER_SIZE)}
|
||||
kInitialBufferSize)}
|
||||
, items_{rhs.items_, monotonic_resource_.get()}
|
||||
, dropsDestroyed_{rhs.dropsDestroyed_} {};
|
||||
|
||||
|
||||
@@ -25,11 +25,11 @@ namespace detail {
|
||||
Number
|
||||
reduceOffer(auto const& amount)
|
||||
{
|
||||
static Number const kREDUCED_OFFER_PCT(9999, -4);
|
||||
static Number const kReducedOfferPct(9999, -4);
|
||||
|
||||
// Make sure the result is always less than amount or zero.
|
||||
NumberRoundModeGuard const mg(Number::RoundingMode::TowardsZero);
|
||||
return amount * kREDUCED_OFFER_PCT;
|
||||
return amount * kReducedOfferPct;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
@@ -177,7 +177,7 @@ getAMMOfferStartWithTakerGets(
|
||||
Quality const& targetQuality,
|
||||
std::uint16_t const& tfee)
|
||||
{
|
||||
if (targetQuality.rate() == beast::kZERO)
|
||||
if (targetQuality.rate() == beast::kZero)
|
||||
return std::nullopt;
|
||||
|
||||
NumberRoundModeGuard const mg(Number::RoundingMode::ToNearest);
|
||||
@@ -244,7 +244,7 @@ getAMMOfferStartWithTakerPays(
|
||||
Quality const& targetQuality,
|
||||
std::uint16_t tfee)
|
||||
{
|
||||
if (targetQuality.rate() == beast::kZERO)
|
||||
if (targetQuality.rate() == beast::kZero)
|
||||
return std::nullopt;
|
||||
|
||||
NumberRoundModeGuard const mg(Number::RoundingMode::ToNearest);
|
||||
|
||||
@@ -19,14 +19,10 @@ namespace credentials {
|
||||
|
||||
// Check if credential sfExpiration field has passed ledger's parentCloseTime
|
||||
bool
|
||||
checkExpired(std::shared_ptr<SLE const> const& sleCredential, NetClock::time_point const& closed);
|
||||
|
||||
// Return true if any expired credential was found in arr (and deleted)
|
||||
bool
|
||||
removeExpired(ApplyView& view, STVector256 const& arr, beast::Journal const j);
|
||||
checkExpired(SLE const& sleCredential, NetClock::time_point const& closed);
|
||||
|
||||
// Actually remove a credentials object from the ledger
|
||||
TER
|
||||
[[nodiscard]] TER
|
||||
deleteSLE(ApplyView& view, std::shared_ptr<SLE> const& sleCredential, beast::Journal j);
|
||||
|
||||
// Amendment and parameters checks for sfCredentialIDs field
|
||||
|
||||
@@ -70,21 +70,21 @@ escrowUnlockApplyHelper<Issue>(
|
||||
initialBalance.get<Issue>().account = noAccount();
|
||||
|
||||
if (TER const ter = trustCreate(
|
||||
view, // payment sandbox
|
||||
recvLow, // is dest low?
|
||||
issuer, // source
|
||||
receiver, // destination
|
||||
trustLineKey.key, // ledger index
|
||||
sleDest, // Account to add to
|
||||
false, // authorize account
|
||||
(sleDest->getFlags() & lsfDefaultRipple) == 0, //
|
||||
false, // freeze trust line
|
||||
false, // deep freeze trust line
|
||||
initialBalance, // zero initial balance
|
||||
Issue(currency, receiver), // limit of zero
|
||||
0, // quality in
|
||||
0, // quality out
|
||||
journal); // journal
|
||||
view, // payment sandbox
|
||||
recvLow, // is dest low?
|
||||
issuer, // source
|
||||
receiver, // destination
|
||||
trustLineKey.key, // ledger index
|
||||
sleDest, // Account to add to
|
||||
false, // authorize account
|
||||
!sleDest->isFlag(lsfDefaultRipple), //
|
||||
false, // freeze trust line
|
||||
false, // deep freeze trust line
|
||||
initialBalance, // zero initial balance
|
||||
Issue(currency, receiver), // limit of zero
|
||||
0, // quality in
|
||||
0, // quality out
|
||||
journal); // journal
|
||||
!isTesSuccess(ter))
|
||||
{
|
||||
return ter; // LCOV_EXCL_LINE
|
||||
@@ -111,7 +111,7 @@ escrowUnlockApplyHelper<Issue>(
|
||||
// whereas in a normal payment, the transfer fee is taken on top of the
|
||||
// sending amount.
|
||||
auto finalAmt = amount;
|
||||
if ((!senderIssuer && !receiverIssuer) && lockedRate != kPARITY_RATE)
|
||||
if ((!senderIssuer && !receiverIssuer) && lockedRate != kParityRate)
|
||||
{
|
||||
// compute transfer fee, if any
|
||||
auto const xferFee =
|
||||
@@ -211,7 +211,7 @@ escrowUnlockApplyHelper<MPTIssue>(
|
||||
// whereas in a normal payment, the transfer fee is taken on top of the
|
||||
// sending amount.
|
||||
auto finalAmt = amount;
|
||||
if ((!senderIssuer && !receiverIssuer) && lockedRate != kPARITY_RATE)
|
||||
if ((!senderIssuer && !receiverIssuer) && lockedRate != kParityRate)
|
||||
{
|
||||
// compute transfer fee, if any
|
||||
auto const xferFee = amount.value() - divideRound(amount, lockedRate, amount.asset(), true);
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace xrpl {
|
||||
bool
|
||||
checkLendingProtocolDependencies(Rules const& rules, STTx const& tx);
|
||||
|
||||
static constexpr std::uint32_t kSECONDS_IN_YEAR = 365 * 24 * 60 * 60;
|
||||
static constexpr std::uint32_t kSecondsInYear = 365 * 24 * 60 * 60;
|
||||
|
||||
Number
|
||||
loanPeriodicRate(TenthBips32 interestRate, std::uint32_t paymentInterval);
|
||||
@@ -42,14 +42,14 @@ struct LoanPaymentParts
|
||||
// The amount of principal paid that reduces the loan balance.
|
||||
// This amount is subtracted from sfPrincipalOutstanding in the Loan object
|
||||
// and paid to the Vault
|
||||
Number principalPaid = kNUM_ZERO;
|
||||
Number principalPaid = kNumZero;
|
||||
|
||||
// The total amount of interest paid to the Vault.
|
||||
// This includes:
|
||||
// - Tracked interest from the amortization schedule
|
||||
// - Untracked interest (e.g., late payment penalty interest)
|
||||
// This value is always non-negative.
|
||||
Number interestPaid = kNUM_ZERO;
|
||||
Number interestPaid = kNumZero;
|
||||
|
||||
// The change in the loan's total value outstanding.
|
||||
// - If valueChange < 0: Loan value decreased
|
||||
@@ -62,7 +62,7 @@ struct LoanPaymentParts
|
||||
// - Late payments add penalty interest to the loan value
|
||||
// - Early full payment may increase or decrease the loan value based on
|
||||
// terms
|
||||
Number valueChange = kNUM_ZERO;
|
||||
Number valueChange = kNumZero;
|
||||
|
||||
/* The total amount of fees paid to the Broker.
|
||||
* This includes:
|
||||
@@ -70,7 +70,7 @@ struct LoanPaymentParts
|
||||
* - Untracked fees (e.g., late payment fees, service fees, origination
|
||||
* fees) This value is always non-negative.
|
||||
*/
|
||||
Number feePaid = kNUM_ZERO;
|
||||
Number feePaid = kNumZero;
|
||||
|
||||
LoanPaymentParts&
|
||||
operator+=(LoanPaymentParts const& other);
|
||||
@@ -161,7 +161,7 @@ adjustImpreciseNumber(
|
||||
{
|
||||
value = roundToAsset(asset, value + adjustment, vaultScale);
|
||||
|
||||
if (*value < beast::kZERO)
|
||||
if (*value < beast::kZero)
|
||||
value = 0;
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ inline int
|
||||
getAssetsTotalScale(SLE::const_ref vaultSle)
|
||||
{
|
||||
if (!vaultSle)
|
||||
return Number::kMIN_EXPONENT - 1; // LCOV_EXCL_LINE
|
||||
return Number::kMinExponent - 1; // LCOV_EXCL_LINE
|
||||
return scale(vaultSle->at(sfAssetsTotal), vaultSle->at(sfAsset));
|
||||
}
|
||||
|
||||
@@ -184,6 +184,7 @@ checkLoanGuards(
|
||||
|
||||
LoanState
|
||||
computeTheoreticalLoanState(
|
||||
Rules const& rules,
|
||||
Number const& periodicPayment,
|
||||
Number const& periodicRate,
|
||||
std::uint32_t const paymentRemaining,
|
||||
@@ -310,7 +311,7 @@ struct ExtendedPaymentComponents : public PaymentComponents
|
||||
// borrower is sufficient to cover all components of the payment.
|
||||
Number totalDue;
|
||||
|
||||
ExtendedPaymentComponents(PaymentComponents const& p, Number fee, Number interest = kNUM_ZERO)
|
||||
ExtendedPaymentComponents(PaymentComponents const& p, Number fee, Number interest = kNumZero)
|
||||
: PaymentComponents(p)
|
||||
, untrackedManagementFee(fee)
|
||||
, untrackedInterest(interest)
|
||||
@@ -353,6 +354,7 @@ struct LoanStateDeltas
|
||||
|
||||
Expected<std::pair<LoanPaymentParts, LoanProperties>, TER>
|
||||
tryOverpayment(
|
||||
Rules const& rules,
|
||||
Asset const& asset,
|
||||
std::int32_t loanScale,
|
||||
ExtendedPaymentComponents const& overpaymentComponents,
|
||||
@@ -363,11 +365,17 @@ tryOverpayment(
|
||||
TenthBips16 const managementFeeRate,
|
||||
beast::Journal j);
|
||||
|
||||
Number
|
||||
computeRaisedRate(Number const& periodicRate, std::uint32_t paymentsRemaining);
|
||||
[[nodiscard]] Number
|
||||
computePowerMinusOne(Number const& periodicRate, std::uint32_t paymentsRemaining);
|
||||
|
||||
Number
|
||||
computePaymentFactor(Number const& periodicRate, std::uint32_t paymentsRemaining);
|
||||
[[nodiscard]] Number
|
||||
computePowerMinusOneHybrid(Number const& periodicRate, std::uint32_t paymentsRemaining);
|
||||
|
||||
[[nodiscard]] Number
|
||||
computePaymentFactor(
|
||||
Rules const& rules,
|
||||
Number const& periodicRate,
|
||||
std::uint32_t paymentsRemaining);
|
||||
|
||||
std::pair<Number, Number>
|
||||
computeInterestAndFeeParts(
|
||||
@@ -378,12 +386,14 @@ computeInterestAndFeeParts(
|
||||
|
||||
Number
|
||||
loanPeriodicPayment(
|
||||
Rules const& rules,
|
||||
Number const& principalOutstanding,
|
||||
Number const& periodicRate,
|
||||
std::uint32_t paymentsRemaining);
|
||||
|
||||
Number
|
||||
loanPrincipalFromPeriodicPayment(
|
||||
Rules const& rules,
|
||||
Number const& periodicPayment,
|
||||
Number const& periodicRate,
|
||||
std::uint32_t paymentsRemaining);
|
||||
@@ -415,6 +425,7 @@ computeOverpaymentComponents(
|
||||
|
||||
PaymentComponents
|
||||
computePaymentComponents(
|
||||
Rules const& rules,
|
||||
Asset const& asset,
|
||||
std::int32_t scale,
|
||||
Number const& totalValueOutstanding,
|
||||
@@ -438,6 +449,7 @@ operator+(LoanState const& lhs, detail::LoanStateDeltas const& rhs);
|
||||
|
||||
LoanProperties
|
||||
computeLoanProperties(
|
||||
Rules const& rules,
|
||||
Asset const& asset,
|
||||
Number const& principalOutstanding,
|
||||
TenthBips32 interestRate,
|
||||
@@ -448,6 +460,7 @@ computeLoanProperties(
|
||||
|
||||
LoanProperties
|
||||
computeLoanProperties(
|
||||
Rules const& rules,
|
||||
Asset const& asset,
|
||||
Number const& principalOutstanding,
|
||||
Number const& periodicRate,
|
||||
|
||||
@@ -20,7 +20,7 @@ class HTTPClient
|
||||
public:
|
||||
explicit HTTPClient() = default;
|
||||
|
||||
static constexpr auto kMAX_CLIENT_HEADER_BYTES = kilobytes(32);
|
||||
static constexpr auto kMaxClientHeaderBytes = kilobytes(32);
|
||||
|
||||
static void
|
||||
initializeSSLContext(
|
||||
|
||||
@@ -29,7 +29,7 @@ enum class NodeObjectType : std::uint32_t {
|
||||
class NodeObject : public CountedObject<NodeObject>
|
||||
{
|
||||
public:
|
||||
static constexpr std::size_t kKEY_BYTES = 32;
|
||||
static constexpr std::size_t kKeyBytes = 32;
|
||||
|
||||
private:
|
||||
// This hack is used to make the constructor effectively private
|
||||
|
||||
@@ -6,20 +6,16 @@
|
||||
|
||||
namespace xrpl::NodeStore {
|
||||
|
||||
// Need to be named before converting
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-use-enum-class)
|
||||
enum {
|
||||
// This is only used to pre-allocate the array for
|
||||
// batch objects and does not affect the amount written.
|
||||
//
|
||||
BatchWritePreallocationSize = 256,
|
||||
// This is only used to pre-allocate the array for
|
||||
// batch objects and does not affect the amount written.
|
||||
//
|
||||
static constexpr auto kBatchWritePreallocationSize = 256;
|
||||
|
||||
// This sets a limit on the maximum number of writes
|
||||
// in a batch. Actual usage can be twice this since
|
||||
// we have a new batch growing as we write the old.
|
||||
//
|
||||
BatchWriteLimitSize = 65536
|
||||
};
|
||||
// This sets a limit on the maximum number of writes
|
||||
// in a batch. Actual usage can be twice this since
|
||||
// we have a new batch growing as we write the old.
|
||||
//
|
||||
static constexpr auto kBatchWriteLimitSize = 65536;
|
||||
|
||||
/** Return codes from Backend operations. */
|
||||
enum class Status {
|
||||
|
||||
@@ -55,7 +55,7 @@ lz4Compress(void const* in, std::size_t inSize, BufferFactory&& bf)
|
||||
using std::runtime_error;
|
||||
using namespace nudb::detail;
|
||||
std::pair<void const*, std::size_t> result;
|
||||
std::array<std::uint8_t, varint_traits<std::size_t>::kMAX> vi{};
|
||||
std::array<std::uint8_t, varint_traits<std::size_t>::kMax> vi{};
|
||||
auto const n = writeVarint(vi.data(), inSize);
|
||||
auto const outMax = LZ4_compressBound(inSize);
|
||||
std::uint8_t* out = reinterpret_cast<std::uint8_t*>(bf(n + outMax));
|
||||
@@ -254,12 +254,12 @@ nodeobjectCompress(void const* in, std::size_t inSize, BufferFactory&& bf)
|
||||
}
|
||||
}
|
||||
|
||||
std::array<std::uint8_t, varint_traits<std::size_t>::kMAX> vi{};
|
||||
std::array<std::uint8_t, varint_traits<std::size_t>::kMax> vi{};
|
||||
|
||||
constexpr std::size_t kCODEC_TYPE = 1;
|
||||
auto const vn = writeVarint(vi.data(), kCODEC_TYPE);
|
||||
static constexpr std::size_t kCodecType = 1;
|
||||
auto const vn = writeVarint(vi.data(), kCodecType);
|
||||
std::pair<void const*, std::size_t> result;
|
||||
switch (kCODEC_TYPE)
|
||||
switch (kCodecType)
|
||||
{
|
||||
// case 0 was uncompressed data; we always compress now.
|
||||
case 1: // lz4
|
||||
@@ -275,7 +275,7 @@ nodeobjectCompress(void const* in, std::size_t inSize, BufferFactory&& bf)
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Throw<std::logic_error>("nodeobject codec: unknown=" + std::to_string(kCODEC_TYPE));
|
||||
Throw<std::logic_error>("nodeobject codec: unknown=" + std::to_string(kCodecType));
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ struct varint_traits<T, true>
|
||||
{
|
||||
explicit varint_traits() = default;
|
||||
|
||||
static std::size_t constexpr kMAX = (8 * sizeof(T) + 6) / 7;
|
||||
static constexpr std::size_t kMax = (8 * sizeof(T) + 6) / 7;
|
||||
};
|
||||
|
||||
// Returns: Number of bytes consumed or 0 on error,
|
||||
|
||||
@@ -8,21 +8,21 @@
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
std::uint16_t constexpr kTRADING_FEE_THRESHOLD = 1000; // 1%
|
||||
constexpr std::uint16_t kTradingFeeThreshold = 1000; // 1%
|
||||
|
||||
// Auction slot
|
||||
std::uint32_t constexpr kTOTAL_TIME_SLOT_SECS = 24 * 3600;
|
||||
std::uint16_t constexpr kAUCTION_SLOT_TIME_INTERVALS = 20;
|
||||
std::uint16_t constexpr kAUCTION_SLOT_MAX_AUTH_ACCOUNTS = 4;
|
||||
std::uint32_t constexpr kAUCTION_SLOT_FEE_SCALE_FACTOR = 100000;
|
||||
std::uint32_t constexpr kAUCTION_SLOT_DISCOUNTED_FEE_FRACTION = 10;
|
||||
std::uint32_t constexpr kAUCTION_SLOT_MIN_FEE_FRACTION = 25;
|
||||
std::uint32_t constexpr kAUCTION_SLOT_INTERVAL_DURATION =
|
||||
kTOTAL_TIME_SLOT_SECS / kAUCTION_SLOT_TIME_INTERVALS;
|
||||
constexpr std::uint32_t kTotalTimeSlotSecs = 24 * 3600;
|
||||
constexpr std::uint16_t kAuctionSlotTimeIntervals = 20;
|
||||
constexpr std::uint16_t kAuctionSlotMaxAuthAccounts = 4;
|
||||
constexpr std::uint32_t kAuctionSlotFeeScaleFactor = 100000;
|
||||
constexpr std::uint32_t kAuctionSlotDiscountedFeeFraction = 10;
|
||||
constexpr std::uint32_t kAuctionSlotMinFeeFraction = 25;
|
||||
constexpr std::uint32_t kAuctionSlotIntervalDuration =
|
||||
kTotalTimeSlotSecs / kAuctionSlotTimeIntervals;
|
||||
|
||||
// Votes
|
||||
std::uint16_t constexpr kVOTE_MAX_SLOTS = 8;
|
||||
std::uint32_t constexpr kVOTE_WEIGHT_SCALE_FACTOR = 100000;
|
||||
constexpr std::uint16_t kVoteMaxSlots = 8;
|
||||
constexpr std::uint32_t kVoteWeightScaleFactor = 100000;
|
||||
|
||||
class STObject;
|
||||
class STAmount;
|
||||
@@ -77,7 +77,7 @@ ammEnabled(Rules const&);
|
||||
inline Number
|
||||
getFee(std::uint16_t tfee)
|
||||
{
|
||||
return Number{tfee} / kAUCTION_SLOT_FEE_SCALE_FACTOR;
|
||||
return Number{tfee} / kAuctionSlotFeeScaleFactor;
|
||||
}
|
||||
|
||||
/** Get fee multiplier (1 - tfee)
|
||||
|
||||
@@ -25,7 +25,7 @@ public:
|
||||
} // namespace detail
|
||||
|
||||
/** A 160-bit unsigned that uniquely identifies an account. */
|
||||
using AccountID = BaseUint<160, detail::AccountIDTag>;
|
||||
using AccountID = BaseUInt<160, detail::AccountIDTag>;
|
||||
|
||||
/** Convert AccountID to base58 checked string */
|
||||
std::string
|
||||
@@ -69,7 +69,7 @@ toIssuer(AccountID&, std::string const&);
|
||||
inline bool
|
||||
isXRP(AccountID const& c)
|
||||
{
|
||||
return c == beast::kZERO;
|
||||
return c == beast::kZero;
|
||||
}
|
||||
|
||||
// DEPRECATED
|
||||
|
||||
@@ -96,9 +96,9 @@ inline MPTAmount
|
||||
toAmount<MPTAmount>(STAmount const& amt)
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
amt.holds<MPTIssue>() && amt.mantissa() <= kMAX_MP_TOKEN_AMOUNT && amt.exponent() == 0,
|
||||
amt.holds<MPTIssue>() && amt.mantissa() <= kMaxMpTokenAmount && amt.exponent() == 0,
|
||||
"xrpl::toAmount<MPTAmount> : maximum mantissa");
|
||||
if (amt.mantissa() > kMAX_MP_TOKEN_AMOUNT || amt.exponent() != 0)
|
||||
if (amt.mantissa() > kMaxMpTokenAmount || amt.exponent() != 0)
|
||||
Throw<std::runtime_error>("toAmount<MPTAmount>: invalid mantissa or exponent");
|
||||
bool const isNeg = amt.negative();
|
||||
std::int64_t const sMant = isNeg ? -std::int64_t(amt.mantissa()) : amt.mantissa();
|
||||
@@ -167,8 +167,8 @@ toAmount(Asset const& asset, Number const& n, Number::RoundingMode mode = Number
|
||||
}
|
||||
else
|
||||
{
|
||||
constexpr bool kALWAYS_FALSE = !std::is_same_v<T, T>;
|
||||
static_assert(kALWAYS_FALSE, "Unsupported type for toAmount");
|
||||
static constexpr bool kAlwaysFalse = !std::is_same_v<T, T>;
|
||||
static_assert(kAlwaysFalse, "Unsupported type for toAmount");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,30 +178,30 @@ toMaxAmount(Asset const& asset)
|
||||
{
|
||||
if constexpr (std::is_same_v<IOUAmount, T>)
|
||||
{
|
||||
return IOUAmount(STAmount::kMAX_VALUE, STAmount::kMAX_OFFSET);
|
||||
return IOUAmount(STAmount::kMaxValue, STAmount::kMaxOffset);
|
||||
}
|
||||
else if constexpr (std::is_same_v<XRPAmount, T>)
|
||||
{
|
||||
return XRPAmount(static_cast<std::int64_t>(STAmount::kMAX_NATIVE_N));
|
||||
return XRPAmount(static_cast<std::int64_t>(STAmount::kMaxNativeN));
|
||||
}
|
||||
else if constexpr (std::is_same_v<MPTAmount, T>)
|
||||
{
|
||||
return MPTAmount(kMAX_MP_TOKEN_AMOUNT);
|
||||
return MPTAmount(kMaxMpTokenAmount);
|
||||
}
|
||||
else if constexpr (std::is_same_v<STAmount, T>)
|
||||
{
|
||||
return asset.visit(
|
||||
[](Issue const& issue) {
|
||||
if (isXRP(issue))
|
||||
return STAmount(issue, static_cast<std::int64_t>(STAmount::kMAX_NATIVE_N));
|
||||
return STAmount(issue, STAmount::kMAX_VALUE, STAmount::kMAX_OFFSET);
|
||||
return STAmount(issue, static_cast<std::int64_t>(STAmount::kMaxNativeN));
|
||||
return STAmount(issue, STAmount::kMaxValue, STAmount::kMaxOffset);
|
||||
},
|
||||
[](MPTIssue const& issue) { return STAmount(issue, kMAX_MP_TOKEN_AMOUNT); });
|
||||
[](MPTIssue const& issue) { return STAmount(issue, kMaxMpTokenAmount); });
|
||||
}
|
||||
else
|
||||
{
|
||||
constexpr bool kALWAYS_FALSE = !std::is_same_v<T, T>;
|
||||
static_assert(kALWAYS_FALSE, "Unsupported type for toMaxAmount");
|
||||
static constexpr bool kAlwaysFalse = !std::is_same_v<T, T>;
|
||||
static_assert(kAlwaysFalse, "Unsupported type for toMaxAmount");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -233,8 +233,8 @@ getAsset(T const& amt)
|
||||
}
|
||||
else
|
||||
{
|
||||
constexpr bool kALWAYS_FALSE = !std::is_same_v<T, T>;
|
||||
static_assert(kALWAYS_FALSE, "Unsupported type for getIssue");
|
||||
static constexpr bool kAlwaysFalse = !std::is_same_v<T, T>;
|
||||
static_assert(kAlwaysFalse, "Unsupported type for getIssue");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,8 +260,8 @@ get(STAmount const& a)
|
||||
}
|
||||
else
|
||||
{
|
||||
constexpr bool kALWAYS_FALSE = !std::is_same_v<T, T>;
|
||||
static_assert(kALWAYS_FALSE, "Unsupported type for get");
|
||||
constexpr bool kAlwaysFalse = !std::is_same_v<T, T>;
|
||||
static_assert(kAlwaysFalse, "Unsupported type for get");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,49 +35,49 @@ namespace xrpl {
|
||||
namespace RPC {
|
||||
|
||||
template <unsigned int Version>
|
||||
constexpr static std::integral_constant<unsigned, Version> kAPI_VERSION = {};
|
||||
static constexpr std::integral_constant<unsigned, Version> kApiVersion = {};
|
||||
|
||||
constexpr static auto kAPI_INVALID_VERSION = kAPI_VERSION<0>;
|
||||
constexpr static auto kAPI_MINIMUM_SUPPORTED_VERSION = kAPI_VERSION<1>;
|
||||
constexpr static auto kAPI_MAXIMUM_SUPPORTED_VERSION = kAPI_VERSION<2>;
|
||||
constexpr static auto kAPI_VERSION_IF_UNSPECIFIED = kAPI_VERSION<1>;
|
||||
constexpr static auto kAPI_COMMAND_LINE_VERSION = kAPI_VERSION<1>; // TODO Bump to 2 later
|
||||
constexpr static auto kAPI_BETA_VERSION = kAPI_VERSION<3>;
|
||||
constexpr static auto kAPI_MAXIMUM_VALID_VERSION = kAPI_BETA_VERSION;
|
||||
static constexpr auto kApiInvalidVersion = kApiVersion<0>;
|
||||
static constexpr auto kApiMinimumSupportedVersion = kApiVersion<1>;
|
||||
static constexpr auto kApiMaximumSupportedVersion = kApiVersion<2>;
|
||||
static constexpr auto kApiVersionIfUnspecified = kApiVersion<1>;
|
||||
static constexpr auto kApiCommandLineVersion = kApiVersion<1>; // TODO Bump to 2 later
|
||||
static constexpr auto kApiBetaVersion = kApiVersion<3>;
|
||||
static constexpr auto kApiMaximumValidVersion = kApiBetaVersion;
|
||||
|
||||
static_assert(kAPI_INVALID_VERSION < kAPI_MINIMUM_SUPPORTED_VERSION);
|
||||
static_assert(kApiInvalidVersion < kApiMinimumSupportedVersion);
|
||||
static_assert(
|
||||
kAPI_VERSION_IF_UNSPECIFIED >= kAPI_MINIMUM_SUPPORTED_VERSION &&
|
||||
kAPI_VERSION_IF_UNSPECIFIED <= kAPI_MAXIMUM_SUPPORTED_VERSION);
|
||||
kApiVersionIfUnspecified >= kApiMinimumSupportedVersion &&
|
||||
kApiVersionIfUnspecified <= kApiMaximumSupportedVersion);
|
||||
static_assert(
|
||||
kAPI_COMMAND_LINE_VERSION >= kAPI_MINIMUM_SUPPORTED_VERSION &&
|
||||
kAPI_COMMAND_LINE_VERSION <= kAPI_MAXIMUM_SUPPORTED_VERSION);
|
||||
static_assert(kAPI_MAXIMUM_SUPPORTED_VERSION >= kAPI_MINIMUM_SUPPORTED_VERSION);
|
||||
static_assert(kAPI_BETA_VERSION >= kAPI_MAXIMUM_SUPPORTED_VERSION);
|
||||
static_assert(kAPI_MAXIMUM_VALID_VERSION >= kAPI_MAXIMUM_SUPPORTED_VERSION);
|
||||
kApiCommandLineVersion >= kApiMinimumSupportedVersion &&
|
||||
kApiCommandLineVersion <= kApiMaximumSupportedVersion);
|
||||
static_assert(kApiMaximumSupportedVersion >= kApiMinimumSupportedVersion);
|
||||
static_assert(kApiBetaVersion >= kApiMaximumSupportedVersion);
|
||||
static_assert(kApiMaximumValidVersion >= kApiMaximumSupportedVersion);
|
||||
|
||||
inline void
|
||||
setVersion(json::Value& parent, unsigned int apiVersion, bool betaEnabled)
|
||||
{
|
||||
XRPL_ASSERT(apiVersion != kAPI_INVALID_VERSION, "xrpl::RPC::setVersion : input is valid");
|
||||
XRPL_ASSERT(apiVersion != kApiInvalidVersion, "xrpl::RPC::setVersion : input is valid");
|
||||
|
||||
auto& retObj = parent[jss::version] = json::ObjectValue;
|
||||
auto& retObj = parent[jss::version] = json::ValueType::Object;
|
||||
|
||||
if (apiVersion == kAPI_VERSION_IF_UNSPECIFIED)
|
||||
if (apiVersion == kApiVersionIfUnspecified)
|
||||
{
|
||||
// API version numbers used in API version 1
|
||||
static beast::SemanticVersion const kFIRST_VERSION{"1.0.0"};
|
||||
static beast::SemanticVersion const kGOOD_VERSION{"1.0.0"};
|
||||
static beast::SemanticVersion const kLAST_VERSION{"1.0.0"};
|
||||
static beast::SemanticVersion const kFirstVersion{"1.0.0"};
|
||||
static beast::SemanticVersion const kGoodVersion{"1.0.0"};
|
||||
static beast::SemanticVersion const kLastVersion{"1.0.0"};
|
||||
|
||||
retObj[jss::first] = kFIRST_VERSION.print();
|
||||
retObj[jss::good] = kGOOD_VERSION.print();
|
||||
retObj[jss::last] = kLAST_VERSION.print();
|
||||
retObj[jss::first] = kFirstVersion.print();
|
||||
retObj[jss::good] = kGoodVersion.print();
|
||||
retObj[jss::last] = kLastVersion.print();
|
||||
}
|
||||
else
|
||||
{
|
||||
retObj[jss::first] = kAPI_MINIMUM_SUPPORTED_VERSION.value;
|
||||
retObj[jss::last] = betaEnabled ? kAPI_BETA_VERSION : kAPI_MAXIMUM_SUPPORTED_VERSION;
|
||||
retObj[jss::first] = kApiMinimumSupportedVersion.value;
|
||||
retObj[jss::last] = betaEnabled ? kApiBetaVersion : kApiMaximumSupportedVersion;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,9 +98,9 @@ setVersion(json::Value& parent, unsigned int apiVersion, bool betaEnabled)
|
||||
inline unsigned int
|
||||
getAPIVersionNumber(json::Value const& jv, bool betaEnabled)
|
||||
{
|
||||
static json::Value const kMIN_VERSION(RPC::kAPI_MINIMUM_SUPPORTED_VERSION);
|
||||
static json::Value const kMinVersion(RPC::kApiMinimumSupportedVersion);
|
||||
json::Value const maxVersion(
|
||||
betaEnabled ? RPC::kAPI_BETA_VERSION : RPC::kAPI_MAXIMUM_SUPPORTED_VERSION);
|
||||
betaEnabled ? RPC::kApiBetaVersion : RPC::kApiMaximumSupportedVersion);
|
||||
|
||||
if (jv.isObject())
|
||||
{
|
||||
@@ -109,18 +109,18 @@ getAPIVersionNumber(json::Value const& jv, bool betaEnabled)
|
||||
auto const specifiedVersion = jv[jss::api_version];
|
||||
if (!specifiedVersion.isInt() && !specifiedVersion.isUInt())
|
||||
{
|
||||
return RPC::kAPI_INVALID_VERSION;
|
||||
return RPC::kApiInvalidVersion;
|
||||
}
|
||||
auto const specifiedVersionInt = specifiedVersion.asInt();
|
||||
if (specifiedVersionInt < kMIN_VERSION || specifiedVersionInt > maxVersion)
|
||||
if (specifiedVersionInt < kMinVersion || specifiedVersionInt > maxVersion)
|
||||
{
|
||||
return RPC::kAPI_INVALID_VERSION;
|
||||
return RPC::kApiInvalidVersion;
|
||||
}
|
||||
return specifiedVersionInt;
|
||||
}
|
||||
}
|
||||
|
||||
return RPC::kAPI_VERSION_IF_UNSPECIFIED;
|
||||
return RPC::kApiVersionIfUnspecified;
|
||||
}
|
||||
|
||||
} // namespace RPC
|
||||
@@ -128,33 +128,33 @@ getAPIVersionNumber(json::Value const& jv, bool betaEnabled)
|
||||
template <unsigned MinVer, unsigned MaxVer, typename Fn, typename... Args>
|
||||
void
|
||||
forApiVersions(Fn const& fn, Args&&... args)
|
||||
requires //
|
||||
(MaxVer >= MinVer) && //
|
||||
(MinVer >= RPC::kAPI_MINIMUM_SUPPORTED_VERSION) && //
|
||||
(RPC::kAPI_MAXIMUM_VALID_VERSION >= MaxVer) && requires {
|
||||
requires //
|
||||
(MaxVer >= MinVer) && //
|
||||
(MinVer >= RPC::kApiMinimumSupportedVersion) && //
|
||||
(RPC::kApiMaximumValidVersion >= MaxVer) && requires {
|
||||
fn(std::integral_constant<unsigned int, MinVer>{}, std::forward<Args>(args)...);
|
||||
fn(std::integral_constant<unsigned int, MaxVer>{}, std::forward<Args>(args)...);
|
||||
}
|
||||
{
|
||||
constexpr auto kSIZE = MaxVer + 1 - MinVer;
|
||||
static constexpr auto kSize = MaxVer + 1 - MinVer;
|
||||
[&]<std::size_t... Offset>(std::index_sequence<Offset...>) {
|
||||
// NOLINTBEGIN(bugprone-use-after-move)
|
||||
(((void)fn(
|
||||
std::integral_constant<unsigned int, MinVer + Offset>{}, std::forward<Args>(args)...)),
|
||||
...);
|
||||
// NOLINTEND(bugprone-use-after-move)
|
||||
}(std::make_index_sequence<kSIZE>{});
|
||||
}(std::make_index_sequence<kSize>{});
|
||||
}
|
||||
|
||||
template <typename Fn, typename... Args>
|
||||
void
|
||||
forAllApiVersions(Fn const& fn, Args&&... args)
|
||||
requires requires {
|
||||
forApiVersions<RPC::kAPI_MINIMUM_SUPPORTED_VERSION, RPC::kAPI_MAXIMUM_VALID_VERSION>(
|
||||
forApiVersions<RPC::kApiMinimumSupportedVersion, RPC::kApiMaximumValidVersion>(
|
||||
fn, std::forward<Args>(args)...);
|
||||
}
|
||||
{
|
||||
forApiVersions<RPC::kAPI_MINIMUM_SUPPORTED_VERSION, RPC::kAPI_MAXIMUM_VALID_VERSION>(
|
||||
forApiVersions<RPC::kApiMinimumSupportedVersion, RPC::kApiMaximumValidVersion>(
|
||||
fn, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
|
||||
@@ -148,10 +148,10 @@ public:
|
||||
};
|
||||
|
||||
template <ValidIssueType TIss>
|
||||
constexpr bool kIS_ISSUE_V = std::is_same_v<TIss, Issue>;
|
||||
constexpr bool kIsIssueV = std::is_same_v<TIss, Issue>;
|
||||
|
||||
template <ValidIssueType TIss>
|
||||
constexpr bool kIS_MPTISSUE_V = std::is_same_v<TIss, MPTIssue>;
|
||||
constexpr bool kIsMptissueV = std::is_same_v<TIss, MPTIssue>;
|
||||
|
||||
inline json::Value
|
||||
toJson(Asset const& asset)
|
||||
@@ -242,7 +242,7 @@ operator<=>(Asset const& lhs, Asset const& rhs)
|
||||
{
|
||||
return std::weak_ordering(lhs <=> rhs);
|
||||
}
|
||||
else if constexpr (kIS_ISSUE_V<TLhs> && kIS_MPTISSUE_V<TRhs>)
|
||||
else if constexpr (kIsIssueV<TLhs> && kIsMptissueV<TRhs>)
|
||||
{
|
||||
return std::weak_ordering::greater;
|
||||
}
|
||||
|
||||
@@ -65,11 +65,11 @@
|
||||
namespace xrpl {
|
||||
|
||||
// Feature names must not exceed this length (in characters, excluding the null terminator).
|
||||
static constexpr std::size_t kMAX_FEATURE_NAME_SIZE = 63;
|
||||
static constexpr std::size_t kMaxFeatureNameSize = 63;
|
||||
// Reserve this exact feature-name length (in characters/bytes, excluding the null terminator)
|
||||
// so that a 32-byte uint256 (for example, in WASM or other interop contexts) can be used
|
||||
// as a compact, fixed-size feature selector without conflicting with human-readable names.
|
||||
static constexpr std::size_t kRESERVED_FEATURE_NAME_SIZE = 32;
|
||||
static constexpr std::size_t kReservedFeatureNameSize = 32;
|
||||
|
||||
// Both validFeatureNameSize and validFeatureName are consteval functions that can be used in
|
||||
// static_asserts to validate feature names at compile time. They are only used inside
|
||||
@@ -81,14 +81,14 @@ validFeatureNameSize(auto fn) -> bool
|
||||
{
|
||||
constexpr char const* kN = fn();
|
||||
// Note, std::strlen is not constexpr, we need to implement our own here.
|
||||
constexpr std::size_t kLEN = [](auto n) {
|
||||
constexpr std::size_t kLen = [](auto n) {
|
||||
std::size_t ret = 0;
|
||||
for (auto ptr = n; *ptr != '\0'; ret++, ++ptr)
|
||||
;
|
||||
return ret;
|
||||
}(kN);
|
||||
return kLEN != kRESERVED_FEATURE_NAME_SIZE && //
|
||||
kLEN <= kMAX_FEATURE_NAME_SIZE;
|
||||
return kLen != kReservedFeatureNameSize && //
|
||||
kLen <= kMaxFeatureNameSize;
|
||||
}
|
||||
|
||||
consteval auto
|
||||
@@ -136,7 +136,7 @@ namespace detail {
|
||||
// Feature.cpp. Because it's only used to reserve storage, and determine how
|
||||
// large to make the FeatureBitset, it MAY be larger. It MUST NOT be less than
|
||||
// the actual number of amendments. A LogicError on startup will verify this.
|
||||
static constexpr std::size_t kNUM_FEATURES =
|
||||
static constexpr std::size_t kNumFeatures =
|
||||
(0 +
|
||||
#include <xrpl/protocol/detail/features.macro>
|
||||
);
|
||||
@@ -184,9 +184,9 @@ bitsetIndexToFeature(size_t i);
|
||||
std::string
|
||||
featureToName(uint256 const& f);
|
||||
|
||||
class FeatureBitset : private std::bitset<detail::kNUM_FEATURES>
|
||||
class FeatureBitset : private std::bitset<detail::kNumFeatures>
|
||||
{
|
||||
using base = std::bitset<detail::kNUM_FEATURES>;
|
||||
using base = std::bitset<detail::kNumFeatures>;
|
||||
|
||||
template <class... Fs>
|
||||
void
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace xrpl {
|
||||
|
||||
// Deprecated constant for backwards compatibility with pre-XRPFees amendment.
|
||||
// This was the reference fee units used in the old fee calculation.
|
||||
inline constexpr std::uint32_t kFEE_UNITS_DEPRECATED = 10;
|
||||
inline constexpr std::uint32_t kFeeUnitsDeprecated = 10;
|
||||
|
||||
/** Reflects the fee settings for a particular ledger.
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ public:
|
||||
|
||||
inline IOUAmount::IOUAmount(beast::Zero)
|
||||
{
|
||||
*this = beast::kZERO;
|
||||
*this = beast::kZero;
|
||||
}
|
||||
|
||||
inline IOUAmount::IOUAmount(mantissa_type mantissa, exponent_type exponent)
|
||||
|
||||
@@ -82,7 +82,7 @@ struct BookT
|
||||
Keylet
|
||||
operator()(Book const& b) const;
|
||||
};
|
||||
static BookT const kBOOK{};
|
||||
static BookT const kBook{};
|
||||
|
||||
/** The index of a trust line for a given currency
|
||||
|
||||
@@ -126,7 +126,7 @@ struct NextT
|
||||
Keylet
|
||||
operator()(Keylet const& k) const;
|
||||
};
|
||||
static NextT const kNEXT{};
|
||||
static NextT const kNext{};
|
||||
|
||||
/** A ticket belonging to an account */
|
||||
struct TicketT
|
||||
@@ -145,7 +145,7 @@ struct TicketT
|
||||
return {ltTICKET, key};
|
||||
}
|
||||
};
|
||||
static TicketT const kTICKET{};
|
||||
static TicketT const kTicket{};
|
||||
|
||||
/** A SignerList */
|
||||
Keylet
|
||||
@@ -373,7 +373,7 @@ struct KeyletDesc
|
||||
|
||||
// This list should include all of the keylet functions that take a single
|
||||
// AccountID parameter.
|
||||
std::array<KeyletDesc<AccountID const&>, 6> const kDIRECT_ACCOUNT_KEYLETS{
|
||||
std::array<KeyletDesc<AccountID const&>, 6> const kDirectAccountKeylets{
|
||||
{{.function = &keylet::account, .expectedLEName = jss::AccountRoot, .includeInTests = false},
|
||||
{.function = &keylet::ownerDir, .expectedLEName = jss::DirectoryNode, .includeInTests = true},
|
||||
{.function = &keylet::signers, .expectedLEName = jss::SignerList, .includeInTests = true},
|
||||
|
||||
@@ -96,16 +96,16 @@ operator<=>(Issue const& lhs, Issue const& rhs)
|
||||
inline Issue const&
|
||||
xrpIssue()
|
||||
{
|
||||
static Issue const kISSUE{xrpCurrency(), xrpAccount()};
|
||||
return kISSUE;
|
||||
static Issue const kIssue{xrpCurrency(), xrpAccount()};
|
||||
return kIssue;
|
||||
}
|
||||
|
||||
/** Returns an asset specifier that represents no account and currency. */
|
||||
inline Issue const&
|
||||
noIssue()
|
||||
{
|
||||
static Issue const kISSUE{noCurrency(), noAccount()};
|
||||
return kISSUE;
|
||||
static Issue const kIssue{noCurrency(), noAccount()};
|
||||
return kIssue;
|
||||
}
|
||||
|
||||
inline bool
|
||||
|
||||
@@ -26,12 +26,12 @@ struct LedgerHeader
|
||||
//
|
||||
|
||||
// Closed means "tx set already determined"
|
||||
uint256 hash = beast::kZERO;
|
||||
uint256 txHash = beast::kZERO;
|
||||
uint256 accountHash = beast::kZERO;
|
||||
uint256 parentHash = beast::kZERO;
|
||||
uint256 hash = beast::kZero;
|
||||
uint256 txHash = beast::kZero;
|
||||
uint256 accountHash = beast::kZero;
|
||||
uint256 parentHash = beast::kZero;
|
||||
|
||||
XRPAmount drops = beast::kZERO;
|
||||
XRPAmount drops = beast::kZero;
|
||||
|
||||
// If validated is false, it means "not yet validated."
|
||||
// Once validated is true, it will never be set false at a later time.
|
||||
@@ -53,12 +53,12 @@ struct LedgerHeader
|
||||
};
|
||||
|
||||
// ledger close flags
|
||||
static std::uint32_t const kS_LCF_NO_CONSENSUS_TIME = 0x01;
|
||||
static std::uint32_t const kSLcfNoConsensusTime = 0x01;
|
||||
|
||||
inline bool
|
||||
getCloseAgree(LedgerHeader const& info)
|
||||
{
|
||||
return (info.closeFlags & kS_LCF_NO_CONSENSUS_TIME) == 0;
|
||||
return (info.closeFlags & kSLcfNoConsensusTime) == 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -88,7 +88,7 @@ constexpr MPTAmount::MPTAmount(value_type value) : value_(value)
|
||||
|
||||
constexpr MPTAmount::MPTAmount(beast::Zero)
|
||||
{
|
||||
*this = beast::kZERO;
|
||||
*this = beast::kZero;
|
||||
}
|
||||
|
||||
constexpr MPTAmount&
|
||||
|
||||
@@ -15,14 +15,14 @@ namespace xrpl {
|
||||
|
||||
namespace detail {
|
||||
template <typename T>
|
||||
constexpr bool kIS_INTEGRAL_CONSTANT = false;
|
||||
constexpr bool kIsIntegralConstant = false;
|
||||
template <typename I, auto A>
|
||||
constexpr bool kIS_INTEGRAL_CONSTANT<std::integral_constant<I, A>&> = true;
|
||||
constexpr bool kIsIntegralConstant<std::integral_constant<I, A>&> = true;
|
||||
template <typename I, auto A>
|
||||
constexpr bool kIS_INTEGRAL_CONSTANT<std::integral_constant<I, A> const&> = true;
|
||||
constexpr bool kIsIntegralConstant<std::integral_constant<I, A> const&> = true;
|
||||
|
||||
template <typename T>
|
||||
concept some_integral_constant = detail::kIS_INTEGRAL_CONSTANT<T&>;
|
||||
concept some_integral_constant = detail::kIsIntegralConstant<T&>;
|
||||
|
||||
// This class is designed to wrap a collection of _almost_ identical json::Value
|
||||
// objects, indexed by version (i.e. there is some mapping of version to object
|
||||
@@ -47,8 +47,8 @@ struct MultiApiJson
|
||||
return (v < MinVer) ? 0 : static_cast<std::size_t>(v - MinVer);
|
||||
}
|
||||
|
||||
constexpr static std::size_t kSIZE = MaxVer + 1 - MinVer;
|
||||
std::array<json::Value, kSIZE> val = {};
|
||||
static constexpr std::size_t kSize = MaxVer + 1 - MinVer;
|
||||
std::array<json::Value, kSize> val = {};
|
||||
|
||||
explicit MultiApiJson(json::Value const& init = {})
|
||||
{
|
||||
@@ -80,7 +80,7 @@ struct MultiApiJson
|
||||
|
||||
if (count == 0)
|
||||
return IsMemberResult::None;
|
||||
return count < kSIZE ? IsMemberResult::Some : IsMemberResult::All;
|
||||
return count < kSize ? IsMemberResult::Some : IsMemberResult::All;
|
||||
}
|
||||
|
||||
static constexpr struct VisitorT final
|
||||
@@ -100,7 +100,7 @@ struct MultiApiJson
|
||||
std::integral_constant<unsigned int, Version>,
|
||||
Args&&...>
|
||||
{
|
||||
static_assert(valid(Version) && index(Version) >= 0 && index(Version) < kSIZE);
|
||||
static_assert(valid(Version) && index(Version) >= 0 && index(Version) < kSize);
|
||||
return std::invoke(fn, json.val[index(Version)], version, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ struct MultiApiJson
|
||||
operator()(Json& json, std::integral_constant<unsigned int, Version> const, Fn fn) const
|
||||
-> std::invoke_result_t<Fn, decltype(json.val[0])>
|
||||
{
|
||||
static_assert(valid(Version) && index(Version) >= 0 && index(Version) < kSIZE);
|
||||
static_assert(valid(Version) && index(Version) >= 0 && index(Version) < kSize);
|
||||
return std::invoke(fn, json.val[index(Version)]);
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ struct MultiApiJson
|
||||
-> std::invoke_result_t<Fn, decltype(json.val[0]), Version, Args&&...>
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
valid(version) && index(version) >= 0 && index(version) < kSIZE,
|
||||
valid(version) && index(version) >= 0 && index(version) < kSize,
|
||||
"xrpl::detail::MultiApijson::operator<Args...>() : valid "
|
||||
"version");
|
||||
return std::invoke(fn, json.val[index(version)], version, std::forward<Args>(args)...);
|
||||
@@ -139,20 +139,20 @@ struct MultiApiJson
|
||||
-> std::invoke_result_t<Fn, decltype(json.val[0])>
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
valid(version) && index(version) >= 0 && index(version) < kSIZE,
|
||||
valid(version) && index(version) >= 0 && index(version) < kSize,
|
||||
"xrpl::detail::MultiApijson::operator() : valid version");
|
||||
return std::invoke(fn, json.val[index(version)]);
|
||||
}
|
||||
} kVISITOR = {};
|
||||
} kVisitor = {};
|
||||
|
||||
auto
|
||||
visit()
|
||||
{
|
||||
return [self = this](auto... args)
|
||||
requires requires {
|
||||
kVISITOR(std::declval<MultiApiJson&>(), std::declval<decltype(args)>()...);
|
||||
kVisitor(std::declval<MultiApiJson&>(), std::declval<decltype(args)>()...);
|
||||
}
|
||||
{ return kVISITOR(*self, std::forward<decltype(args)>(args)...); };
|
||||
{ return kVisitor(*self, std::forward<decltype(args)>(args)...); };
|
||||
}
|
||||
|
||||
[[nodiscard]] auto
|
||||
@@ -160,27 +160,27 @@ struct MultiApiJson
|
||||
{
|
||||
return [self = this](auto... args)
|
||||
requires requires {
|
||||
kVISITOR(std::declval<MultiApiJson const&>(), std::declval<decltype(args)>()...);
|
||||
kVisitor(std::declval<MultiApiJson const&>(), std::declval<decltype(args)>()...);
|
||||
}
|
||||
{ return kVISITOR(*self, std::forward<decltype(args)>(args)...); };
|
||||
{ return kVisitor(*self, std::forward<decltype(args)>(args)...); };
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
auto
|
||||
visit(Args... args) -> std::invoke_result_t<VisitorT, MultiApiJson&, Args...>
|
||||
requires(sizeof...(args) > 0) &&
|
||||
requires { kVISITOR(*this, std::forward<decltype(args)>(args)...); }
|
||||
requires { kVisitor(*this, std::forward<decltype(args)>(args)...); }
|
||||
{
|
||||
return kVISITOR(*this, std::forward<decltype(args)>(args)...);
|
||||
return kVisitor(*this, std::forward<decltype(args)>(args)...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
[[nodiscard]] auto
|
||||
visit(Args... args) const -> std::invoke_result_t<VisitorT, MultiApiJson const&, Args...>
|
||||
requires(sizeof...(args) > 0) &&
|
||||
requires { kVISITOR(*this, std::forward<decltype(args)>(args)...); }
|
||||
requires { kVisitor(*this, std::forward<decltype(args)>(args)...); }
|
||||
{
|
||||
return kVISITOR(*this, std::forward<decltype(args)>(args)...);
|
||||
return kVisitor(*this, std::forward<decltype(args)>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -188,6 +188,6 @@ struct MultiApiJson
|
||||
|
||||
// Wrapper for Json for all supported API versions.
|
||||
using MultiApiJson =
|
||||
detail::MultiApiJson<RPC::kAPI_MINIMUM_SUPPORTED_VERSION, RPC::kAPI_MAXIMUM_VALID_VERSION>;
|
||||
detail::MultiApiJson<RPC::kApiMinimumSupportedVersion, RPC::kApiMaximumValidVersion>;
|
||||
|
||||
} // namespace xrpl
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user