mirror of
https://github.com/XRPLF/rippled.git
synced 2026-07-14 10:40:19 +00:00
Compare commits
8 Commits
bthomee/no
...
bthomee/ig
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
599a651e9e | ||
|
|
dd425ffc6b | ||
|
|
c7adb215ed | ||
|
|
71ee0f400b | ||
|
|
58af1e6f18 | ||
|
|
e372c45836 | ||
|
|
2ebc96a4a6 | ||
|
|
c5a6de6ef7 |
19
.clang-tidy
19
.clang-tidy
@@ -9,37 +9,24 @@ Checks: "-*,
|
||||
|
||||
cppcoreguidelines-*,
|
||||
-cppcoreguidelines-avoid-c-arrays,
|
||||
-cppcoreguidelines-avoid-capturing-lambda-coroutines,
|
||||
-cppcoreguidelines-avoid-const-or-ref-data-members,
|
||||
-cppcoreguidelines-avoid-do-while,
|
||||
-cppcoreguidelines-avoid-goto,
|
||||
-cppcoreguidelines-avoid-magic-numbers,
|
||||
-cppcoreguidelines-avoid-non-const-global-variables,
|
||||
-cppcoreguidelines-avoid-reference-coroutine-parameters,
|
||||
-cppcoreguidelines-c-copy-assignment-signature,
|
||||
-cppcoreguidelines-explicit-virtual-functions,
|
||||
-cppcoreguidelines-interfaces-global-init,
|
||||
-cppcoreguidelines-macro-to-enum,
|
||||
-cppcoreguidelines-macro-usage,
|
||||
-cppcoreguidelines-missing-std-forward,
|
||||
-cppcoreguidelines-narrowing-conversions,
|
||||
-cppcoreguidelines-no-malloc,
|
||||
-cppcoreguidelines-noexcept-destructor,
|
||||
-cppcoreguidelines-noexcept-move-operations,
|
||||
-cppcoreguidelines-noexcept-swap,
|
||||
-cppcoreguidelines-non-private-member-variables-in-classes,
|
||||
-cppcoreguidelines-owning-memory,
|
||||
-cppcoreguidelines-prefer-member-initializer,
|
||||
-cppcoreguidelines-pro-bounds-array-to-pointer-decay,
|
||||
-cppcoreguidelines-pro-bounds-avoid-unchecked-container-access,
|
||||
-cppcoreguidelines-pro-bounds-constant-array-index,
|
||||
-cppcoreguidelines-pro-bounds-pointer-arithmetic,
|
||||
-cppcoreguidelines-pro-type-const-cast,
|
||||
-cppcoreguidelines-pro-type-cstyle-cast,
|
||||
-cppcoreguidelines-pro-type-reinterpret-cast,
|
||||
-cppcoreguidelines-pro-type-union-access,
|
||||
-cppcoreguidelines-pro-type-vararg,
|
||||
-cppcoreguidelines-slicing,
|
||||
-cppcoreguidelines-special-member-functions,
|
||||
|
||||
llvm-namespace-comment,
|
||||
@@ -63,13 +50,7 @@ Checks: "-*,
|
||||
performance-*,
|
||||
-performance-avoid-endl,
|
||||
-performance-enum-size,
|
||||
-performance-inefficient-algorithm,
|
||||
-performance-inefficient-string-concatenation,
|
||||
-performance-no-int-to-ptr,
|
||||
-performance-noexcept-destructor,
|
||||
-performance-noexcept-move-constructor,
|
||||
-performance-noexcept-swap,
|
||||
-performance-type-promotion-in-math-fn,
|
||||
-performance-unnecessary-copy-initialization,
|
||||
-performance-unnecessary-value-param,
|
||||
|
||||
|
||||
1
.github/workflows/conflicting-pr.yml
vendored
1
.github/workflows/conflicting-pr.yml
vendored
@@ -14,6 +14,7 @@ permissions:
|
||||
|
||||
jobs:
|
||||
main:
|
||||
if: ${{ !contains(github.event.pull_request.labels.*.name, 'IgnoreConflicts') }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check if PRs are dirty
|
||||
|
||||
15
docs/build/environment.md
vendored
15
docs/build/environment.md
vendored
@@ -33,9 +33,10 @@ with a single command and without installing anything system-wide:
|
||||
nix --experimental-features 'nix-command flakes' develop
|
||||
```
|
||||
|
||||
On **Linux**, Nix also provides the compiler (GCC). On **macOS**, the shell uses
|
||||
your **system-wide Apple Clang** as the compiler, so you still need to manage
|
||||
its version (see below).
|
||||
On **Linux**, Nix also provides the compiler (GCC); on **macOS**, it provides
|
||||
Clang. If you instead opt to use your system-wide Apple Clang (via
|
||||
`nix develop .#apple-clang`), you need to manage its version yourself (see
|
||||
below).
|
||||
|
||||
See [Using the Nix development shell](./nix.md) for installation and usage
|
||||
details, including how to select a different compiler.
|
||||
@@ -48,10 +49,10 @@ details, including how to select a different compiler.
|
||||
|
||||
### macOS: managing the Apple Clang version
|
||||
|
||||
Because the Nix shell uses the system-wide Apple Clang on macOS, the compiler
|
||||
version is whatever your installed Xcode (or Command Line Tools) provides. The
|
||||
following command should return a version greater than or equal to the
|
||||
[minimum required](#tested-compiler-versions):
|
||||
If you use your system-wide Apple Clang on macOS (via `nix develop .#apple-clang`),
|
||||
the compiler version is whatever your installed Xcode (or Command Line Tools)
|
||||
provides. The following command should return a version greater than or equal to
|
||||
the [minimum required](#tested-compiler-versions):
|
||||
|
||||
```bash
|
||||
clang --version
|
||||
|
||||
40
docs/build/nix.md
vendored
40
docs/build/nix.md
vendored
@@ -9,7 +9,7 @@ This guide explains how to use Nix to set up a reproducible development environm
|
||||
- **Reproducible environment**: Everyone gets the same versions of tools and compilers
|
||||
- **Matches CI**: The Linux CI runs in Docker images built from this exact Nix environment
|
||||
- **No system pollution**: Dependencies are isolated and don't affect your system packages
|
||||
- **Multiple compiler versions**: Easily switch between different GCC and Clang versions
|
||||
- **Consistent compilers**: The GCC and Clang shells use the same versions as CI
|
||||
- **Quick setup**: Get started with a single command
|
||||
- **Works on Linux and macOS**: Consistent experience across platforms
|
||||
|
||||
@@ -31,8 +31,8 @@ This will:
|
||||
|
||||
- Download and set up all required development tools (CMake, Ninja, Conan, etc.)
|
||||
- Configure the appropriate compiler for your platform:
|
||||
- **Linux**: GCC 15.2 (provided by Nix)
|
||||
- **macOS**: Apple Clang (your system compiler)
|
||||
- **Linux**: GCC (provided by Nix)
|
||||
- **macOS**: Clang (provided by Nix)
|
||||
|
||||
The first time you run this command, it will take a few minutes to download and build the environment. Subsequent runs will be much faster.
|
||||
|
||||
@@ -40,12 +40,12 @@ The first time you run this command, it will take a few minutes to download and
|
||||
|
||||
- **Linux**: `nix develop` gives you a shell with all the tooling necessary to
|
||||
develop xrpld and with GCC 15.2 (also provided by Nix). There are no caveats.
|
||||
- **macOS**: `nix develop` gives you a full environment too. The compiler is
|
||||
your system-wide Apple Clang, while every other tool — including Conan — is
|
||||
provided by Nix. Conan has no binary in the Nix cache for macOS, so it is
|
||||
built from source the first time you enter the shell, which makes the initial
|
||||
setup slower (this is handled automatically; see
|
||||
[`nix/devshell.nix`](../../nix/devshell.nix)).
|
||||
- **macOS**: `nix develop` gives you a full environment too, with Clang (and
|
||||
every other tool, including Conan) provided by Nix. To use your system-wide
|
||||
Apple Clang instead, enter `nix develop .#apple-clang`. Conan has no binary in
|
||||
the Nix cache for macOS, so it is built from source the first time you enter
|
||||
the shell, which makes the initial setup slower (this is handled
|
||||
automatically; see [`nix/devshell.nix`](../../nix/devshell.nix)).
|
||||
|
||||
> [!TIP]
|
||||
> To avoid typing `--experimental-features 'nix-command flakes'` every time, you can permanently enable flakes by creating `~/.config/nix/nix.conf`:
|
||||
@@ -62,7 +62,9 @@ The first time you run this command, it will take a few minutes to download and
|
||||
|
||||
### Choosing a different compiler
|
||||
|
||||
A compiler can be chosen by providing its name with the `.#` prefix, e.g. `nix develop .#gcc15`.
|
||||
A compiler can be chosen by providing its name with the `.#` prefix, e.g. `nix develop .#clang`.
|
||||
The `.#gcc` and `.#clang` shells provide the same GCC and Clang versions used in CI
|
||||
(pinned in [`nix/packages.nix`](../../nix/packages.nix)).
|
||||
Use `nix flake show` to see all the available development shells.
|
||||
|
||||
Use `nix develop .#no-compiler` to use the compiler from your system.
|
||||
@@ -70,11 +72,11 @@ Use `nix develop .#no-compiler` to use the compiler from your system.
|
||||
### Example Usage
|
||||
|
||||
```bash
|
||||
# Use GCC 14
|
||||
nix develop .#gcc14
|
||||
# Use GCC (same version as CI)
|
||||
nix develop .#gcc
|
||||
|
||||
# Use Clang 19
|
||||
nix develop .#clang19
|
||||
# Use Clang (same version as CI)
|
||||
nix develop .#clang
|
||||
|
||||
# Use default for your platform
|
||||
nix develop
|
||||
@@ -112,7 +114,15 @@ Once inside the Nix development shell, follow the standard [build instructions](
|
||||
|
||||
[direnv](https://direnv.net/) or [nix-direnv](https://github.com/nix-community/nix-direnv) can automatically activate the Nix development shell when you enter the repository directory.
|
||||
|
||||
This is also the most robust way to use the environment from **any shell** (bash, zsh, fish, …): direnv stays in your current shell and loads the environment _after_ your shell's startup files have run, so the Nix-provided tools take precedence over anything your shell configuration adds to `$PATH`. To use it, install direnv for your shell, then add an `.envrc` containing `use flake` at the repository root and run `direnv allow`.
|
||||
This is also the most robust way to use the environment from **any shell** (bash, zsh, fish, …): direnv stays in your current shell and loads the environment _after_ your shell's startup files have run, so the Nix-provided tools take precedence over anything your shell configuration adds to `$PATH`.
|
||||
|
||||
The repository already ships an `.envrc` at its root that activates the Nix flake development shell, so you don't need to create one. To use it:
|
||||
|
||||
1. [Install direnv](https://direnv.net/docs/installation.html) and [hook it into your shell](https://direnv.net/docs/hook.html) (bash, zsh, fish, …). Installing [nix-direnv](https://github.com/nix-community/nix-direnv) as well is recommended: it caches the shell so that activation is near-instant after the first run.
|
||||
2. Run `direnv allow` once in the repository root. direnv will then load (and reload) the Nix development shell automatically whenever you enter the directory.
|
||||
|
||||
> [!NOTE]
|
||||
> direnv only caches the `.direnv` directory (already listed in `.gitignore`); no other repository files are affected.
|
||||
|
||||
## Conan and Prebuilt Packages
|
||||
|
||||
|
||||
@@ -641,6 +641,9 @@ template <class T>
|
||||
T*
|
||||
SharedWeakUnion<T>::unsafeGetRawPtr() const
|
||||
{
|
||||
// tp_ packs a raw pointer together with a strength bit; recovering the
|
||||
// pointer inherently requires an integer-to-pointer cast.
|
||||
// NOLINTNEXTLINE(performance-no-int-to-ptr)
|
||||
return reinterpret_cast<T*>(tp_ & kPtrMask);
|
||||
}
|
||||
|
||||
|
||||
@@ -138,11 +138,8 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
ConstIterator(Iterator const& orig)
|
||||
ConstIterator(Iterator const& orig) : map(orig.map), ait(orig.ait), mit(orig.mit)
|
||||
{
|
||||
map = orig.map;
|
||||
ait = orig.ait;
|
||||
mit = orig.mit;
|
||||
}
|
||||
|
||||
const_reference
|
||||
@@ -231,11 +228,11 @@ private:
|
||||
|
||||
public:
|
||||
PartitionedUnorderedMap(std::optional<std::size_t> partitions = std::nullopt)
|
||||
{
|
||||
// Set partitions to the number of hardware threads if the parameter
|
||||
// is either empty or set to 0.
|
||||
partitions_ =
|
||||
partitions && (*partitions != 0u) ? *partitions : std::thread::hardware_concurrency();
|
||||
: partitions_(
|
||||
partitions && (*partitions != 0u) ? *partitions : std::thread::hardware_concurrency())
|
||||
{
|
||||
map_.resize(partitions_);
|
||||
XRPL_ASSERT(
|
||||
partitions_,
|
||||
|
||||
@@ -359,6 +359,7 @@ private:
|
||||
deleteElement(Element const* p)
|
||||
{
|
||||
ElementAllocatorTraits::destroy(config_.alloc(), p);
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
|
||||
ElementAllocatorTraits::deallocate(config_.alloc(), const_cast<Element*>(p), 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -528,6 +528,7 @@ private:
|
||||
deleteElement(Element const* p)
|
||||
{
|
||||
ElementAllocatorTraits::destroy(config_.alloc(), p);
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
|
||||
ElementAllocatorTraits::deallocate(config_.alloc(), const_cast<Element*>(p), 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ typeName()
|
||||
if (auto s = abi::__cxa_demangle(name.c_str(), nullptr, nullptr, nullptr))
|
||||
{
|
||||
name = s;
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
|
||||
std::free(s);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -34,11 +34,11 @@ public:
|
||||
createObject();
|
||||
|
||||
private:
|
||||
bool success_;
|
||||
bool success_{false};
|
||||
|
||||
void const* key_;
|
||||
NodeObjectType objectType_;
|
||||
unsigned char const* objectData_;
|
||||
NodeObjectType objectType_{NodeObjectType::Unknown};
|
||||
unsigned char const* objectData_{nullptr};
|
||||
int dataBytes_;
|
||||
};
|
||||
|
||||
|
||||
@@ -240,6 +240,9 @@ private:
|
||||
|
||||
inline STPathElement::STPathElement() : type_(TypeNone), isOffer_(true)
|
||||
{
|
||||
// hashValue_ is derived from the whole object, so it is computed in the body
|
||||
// once every other member is initialized (as in the other constructors).
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer)
|
||||
hashValue_ = getHash(*this);
|
||||
}
|
||||
|
||||
@@ -315,6 +318,9 @@ inline STPathElement::STPathElement(
|
||||
assetID_.visit(
|
||||
[&](Currency const&) { type_ = type_ & (~Type::TypeMpt); },
|
||||
[&](MPTID const&) { type_ = type_ & (~Type::TypeCurrency); });
|
||||
// hashValue_ must be computed after type_ is adjusted above, so this cannot
|
||||
// be a member initializer.
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer)
|
||||
hashValue_ = getHash(*this);
|
||||
}
|
||||
|
||||
|
||||
@@ -50,14 +50,13 @@ public:
|
||||
STVar&
|
||||
operator=(STVar&& rhs);
|
||||
|
||||
STVar(STBase&& t) // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved)
|
||||
STVar(STBase&& t) : p_(t.move(kMaxSize, &d_))
|
||||
{
|
||||
p_ = t.move(kMaxSize, &d_);
|
||||
}
|
||||
|
||||
STVar(STBase const& t)
|
||||
STVar(STBase const& t) : p_(t.copy(kMaxSize, &d_))
|
||||
{
|
||||
p_ = t.copy(kMaxSize, &d_);
|
||||
}
|
||||
|
||||
STVar(DefaultObjectT, SField const& name);
|
||||
|
||||
@@ -138,6 +138,7 @@ intrusive_ptr_release(SHAMapItem const* x)
|
||||
|
||||
// If the slabber doesn't claim this pointer, it was allocated
|
||||
// manually, so we free it manually.
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
|
||||
if (!detail::gSlabber.deallocate(const_cast<std::uint8_t*>(p)))
|
||||
delete[] p;
|
||||
}
|
||||
|
||||
@@ -507,6 +507,9 @@ TaggedPointer::operator=(TaggedPointer&& other)
|
||||
[[nodiscard]] inline std::pair<std::uint8_t, void*>
|
||||
TaggedPointer::decode() const
|
||||
{
|
||||
// tp_ packs a raw pointer together with the tag bits; recovering the
|
||||
// pointer inherently requires an integer-to-pointer cast.
|
||||
// NOLINTNEXTLINE(performance-no-int-to-ptr)
|
||||
return {tp_ & kTagMask, reinterpret_cast<void*>(tp_ & kPtrMask)};
|
||||
}
|
||||
|
||||
@@ -535,6 +538,9 @@ TaggedPointer::getHashesAndChildren() const
|
||||
[[nodiscard]] inline SHAMapHash*
|
||||
TaggedPointer::getHashes() const
|
||||
{
|
||||
// tp_ packs a raw pointer together with the tag bits; recovering the
|
||||
// pointer inherently requires an integer-to-pointer cast.
|
||||
// NOLINTNEXTLINE(performance-no-int-to-ptr)
|
||||
return reinterpret_cast<SHAMapHash*>(tp_ & kPtrMask);
|
||||
};
|
||||
|
||||
|
||||
@@ -92,6 +92,7 @@ public:
|
||||
[[nodiscard]] TOffer<TIn, TOut>&
|
||||
tip() const
|
||||
{
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
|
||||
return const_cast<TOfferStreamBase*>(this)->offer_;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,14 +4,16 @@
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (import ./packages.nix { inherit pkgs; }) commonPackages;
|
||||
inherit (pkgs) lib;
|
||||
inherit (import ./packages.nix { inherit pkgs; })
|
||||
commonPackages
|
||||
gccPackage
|
||||
llvmPackages
|
||||
llvmVersion
|
||||
;
|
||||
|
||||
# Underlying compiler toolchains to wrap. Bump these in one place to
|
||||
# roll the whole environment forward.
|
||||
customGccPackage = pkgs.gcc15;
|
||||
customLlvmPackages = pkgs.llvmPackages_22;
|
||||
customClangMajor = lib.versions.major (lib.getVersion customLlvmPackages.clang-unwrapped);
|
||||
# Underlying compiler toolchains to wrap (versions pinned in packages.nix).
|
||||
customGccPackage = gccPackage;
|
||||
customLlvmPackages = llvmPackages;
|
||||
|
||||
# binutils wrapped to emit binaries that reference the custom glibc
|
||||
# (dynamic linker path, library search path, RPATH).
|
||||
@@ -90,7 +92,7 @@ let
|
||||
extraBuildCommands = ''
|
||||
rsrc="$out/resource-root"
|
||||
mkdir "$rsrc"
|
||||
ln -s "${customLlvmPackages.clang-unwrapped.lib}/lib/clang/${customClangMajor}/include" "$rsrc/include"
|
||||
ln -s "${customLlvmPackages.clang-unwrapped.lib}/lib/clang/${toString llvmVersion}/include" "$rsrc/include"
|
||||
ln -s "${customCompilerRt.out}/lib" "$rsrc/lib"
|
||||
ln -s "${customCompilerRt.out}/share" "$rsrc/share" || true
|
||||
echo "-resource-dir=$rsrc" >> $out/nix-support/cc-cflags
|
||||
|
||||
150
nix/devshell.nix
150
nix/devshell.nix
@@ -1,127 +1,57 @@
|
||||
{ pkgs, ... }:
|
||||
let
|
||||
inherit (import ./packages.nix { inherit pkgs; }) commonPackages;
|
||||
inherit (import ./packages.nix { inherit pkgs; })
|
||||
commonPackages
|
||||
gccVersion
|
||||
llvmPackages
|
||||
;
|
||||
|
||||
# Supported compiler versions
|
||||
gccVersion = pkgs.lib.range 13 15;
|
||||
clangVersions = pkgs.lib.range 18 21;
|
||||
# Plain nixpkgs stdenvs — no custom glibc, unlike ci-env.nix.
|
||||
gccStdenv = pkgs."gcc${toString gccVersion}Stdenv";
|
||||
clangStdenv = llvmPackages.stdenv;
|
||||
|
||||
defaultCompiler = if pkgs.stdenv.isDarwin then "apple-clang" else "gcc";
|
||||
defaultGccVersion = pkgs.lib.last gccVersion;
|
||||
defaultClangVersion = pkgs.lib.last clangVersions;
|
||||
|
||||
strToCompilerEnv =
|
||||
compiler: version:
|
||||
(
|
||||
if compiler == "gcc" then
|
||||
let
|
||||
gccPkg = pkgs."gcc${toString version}Stdenv" or null;
|
||||
in
|
||||
if gccPkg != null && builtins.elem version gccVersion then
|
||||
gccPkg
|
||||
else
|
||||
throw "Invalid GCC version: ${toString version}. Must be one of: ${toString gccVersion}"
|
||||
else if compiler == "clang" then
|
||||
let
|
||||
clangPkg = pkgs."llvmPackages_${toString version}".stdenv or null;
|
||||
in
|
||||
if clangPkg != null && builtins.elem version clangVersions then
|
||||
clangPkg
|
||||
else
|
||||
throw "Invalid Clang version: ${toString version}. Must be one of: ${toString clangVersions}"
|
||||
else if compiler == "apple-clang" || compiler == "none" then
|
||||
pkgs.stdenvNoCC
|
||||
else
|
||||
throw "Invalid compiler: ${compiler}. Must be one of: gcc, clang, apple-clang, none"
|
||||
);
|
||||
|
||||
# Helper function to create a shell with a specific compiler
|
||||
# compilerName is the command used to print the version, or null for none.
|
||||
makeShell =
|
||||
{
|
||||
compiler ? defaultCompiler,
|
||||
version ? (
|
||||
if compiler == "gcc" then
|
||||
defaultGccVersion
|
||||
else if compiler == "clang" then
|
||||
defaultClangVersion
|
||||
else
|
||||
null
|
||||
),
|
||||
stdenv,
|
||||
compilerName,
|
||||
}:
|
||||
let
|
||||
compilerStdEnv = strToCompilerEnv compiler version;
|
||||
|
||||
compilerName =
|
||||
if compiler == "apple-clang" then
|
||||
"clang"
|
||||
else if compiler == "none" then
|
||||
null
|
||||
else
|
||||
compiler;
|
||||
|
||||
gccOnMacWarning =
|
||||
if pkgs.stdenv.isDarwin && compiler == "gcc" then
|
||||
''
|
||||
echo "WARNING: Using GCC on macOS with Conan may not work."
|
||||
echo " Consider using 'nix develop .#clang' or the default shell instead."
|
||||
echo ""
|
||||
''
|
||||
else
|
||||
"";
|
||||
|
||||
compilerVersion =
|
||||
if compilerName != null then
|
||||
if compilerName == null then
|
||||
''echo "No compiler specified - using system compiler"''
|
||||
else
|
||||
''
|
||||
echo "Compiler: "
|
||||
${compilerName} --version
|
||||
''
|
||||
else
|
||||
''
|
||||
echo "No compiler specified - using system compiler"
|
||||
'';
|
||||
|
||||
shellAttrs = {
|
||||
packages = commonPackages;
|
||||
|
||||
shellHook = ''
|
||||
echo "Welcome to xrpld development shell";
|
||||
${gccOnMacWarning}${compilerVersion}
|
||||
'';
|
||||
};
|
||||
in
|
||||
pkgs.mkShell.override { stdenv = compilerStdEnv; } shellAttrs;
|
||||
|
||||
# Generate shells for each compiler version
|
||||
gccShells = builtins.listToAttrs (
|
||||
map (version: {
|
||||
name = "gcc${toString version}";
|
||||
value = makeShell {
|
||||
compiler = "gcc";
|
||||
version = version;
|
||||
};
|
||||
}) gccVersion
|
||||
);
|
||||
|
||||
clangShells = builtins.listToAttrs (
|
||||
map (version: {
|
||||
name = "clang${toString version}";
|
||||
value = makeShell {
|
||||
compiler = "clang";
|
||||
version = version;
|
||||
};
|
||||
}) clangVersions
|
||||
);
|
||||
|
||||
(pkgs.mkShell.override { inherit stdenv; }) {
|
||||
packages = commonPackages;
|
||||
shellHook = ''
|
||||
echo "Welcome to xrpld development shell";
|
||||
${compilerVersion}
|
||||
'';
|
||||
};
|
||||
in
|
||||
gccShells
|
||||
// clangShells
|
||||
// {
|
||||
# Default shells
|
||||
default = makeShell { };
|
||||
gcc = makeShell { compiler = "gcc"; };
|
||||
clang = makeShell { compiler = "clang"; };
|
||||
rec {
|
||||
# macOS: Nix Clang. Linux: Nix GCC.
|
||||
default = if pkgs.stdenv.isDarwin then clang else gcc;
|
||||
|
||||
# No compiler
|
||||
no-compiler = makeShell { compiler = "none"; };
|
||||
apple-clang = makeShell { compiler = "apple-clang"; };
|
||||
gcc = makeShell {
|
||||
stdenv = gccStdenv;
|
||||
compilerName = "gcc";
|
||||
};
|
||||
|
||||
clang = makeShell {
|
||||
stdenv = clangStdenv;
|
||||
compilerName = "clang";
|
||||
};
|
||||
|
||||
# Nix provides no compiler; use the one from your system (e.g. Apple Clang).
|
||||
no-compiler = makeShell {
|
||||
stdenv = pkgs.stdenvNoCC;
|
||||
compilerName = null;
|
||||
};
|
||||
apple-clang = no-compiler;
|
||||
}
|
||||
|
||||
@@ -1,15 +1,33 @@
|
||||
{ pkgs }:
|
||||
let
|
||||
# Compiler versions used across the dev shell and the CI environment.
|
||||
gccVersion = 15;
|
||||
llvmVersion = 22;
|
||||
|
||||
gccPackage = pkgs."gcc${toString gccVersion}";
|
||||
llvmPackages = pkgs."llvmPackages_${toString llvmVersion}";
|
||||
|
||||
# Bound explicitly so it tracks llvmPackages above, not the `with pkgs` default.
|
||||
clangTools = llvmPackages.clang-tools;
|
||||
|
||||
# In LLVM 22, run-clang-tidy.py moved from share/clang/ to bin/, so nixpkgs
|
||||
# clang-tools no longer links it. Wrap it manually.
|
||||
runClangTidy = pkgs.writeShellScriptBin "run-clang-tidy" ''
|
||||
exec ${pkgs.python3}/bin/python3 ${pkgs.llvmPackages_22.clang-unwrapped}/bin/run-clang-tidy "$@"
|
||||
exec ${pkgs.python3}/bin/python3 ${llvmPackages.clang-unwrapped}/bin/run-clang-tidy "$@"
|
||||
'';
|
||||
in
|
||||
{
|
||||
inherit
|
||||
gccVersion
|
||||
llvmVersion
|
||||
gccPackage
|
||||
llvmPackages
|
||||
;
|
||||
|
||||
commonPackages = with pkgs; [
|
||||
ccache
|
||||
clangbuildanalyzer
|
||||
clangTools
|
||||
cmake
|
||||
conan
|
||||
curlMinimal # needed for codecov/codecov-action
|
||||
@@ -23,7 +41,6 @@ in
|
||||
gnumake
|
||||
gnupg # needed for signing commits & codecov/codecov-action
|
||||
graphviz
|
||||
llvmPackages_22.clang-tools
|
||||
less # needed for git diff
|
||||
mold
|
||||
nettools # provides netstat, used to debug failures in CI
|
||||
|
||||
@@ -230,9 +230,8 @@ Writer::~Writer()
|
||||
impl_->finishAll();
|
||||
}
|
||||
|
||||
Writer::Writer(Writer&& w) noexcept
|
||||
Writer::Writer(Writer&& w) noexcept : impl_(std::move(w.impl_))
|
||||
{
|
||||
impl_ = std::move(w.impl_);
|
||||
}
|
||||
|
||||
Writer&
|
||||
|
||||
@@ -5,12 +5,13 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <charconv>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <istream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
|
||||
namespace json {
|
||||
// Implementation of class Reader
|
||||
@@ -605,34 +606,17 @@ bool
|
||||
Reader::decodeDouble(Token& token)
|
||||
{
|
||||
double value = 0;
|
||||
int const bufferSize = 32;
|
||||
int count = 0;
|
||||
int const length = int(token.end - token.start);
|
||||
// Sanity check to avoid buffer overflow exploits.
|
||||
if (length < 0)
|
||||
{
|
||||
return addError("Unable to parse token length", token);
|
||||
}
|
||||
// Avoid using a string constant for the format control string given to
|
||||
// sscanf, as this can cause hard to debug crashes on OS X. See here for
|
||||
// more info:
|
||||
//
|
||||
// http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html
|
||||
char format[] = "%lf";
|
||||
if (length <= bufferSize)
|
||||
{
|
||||
Char buffer[bufferSize + 1];
|
||||
memcpy(buffer, token.start, length);
|
||||
buffer[length] = 0;
|
||||
count = sscanf(buffer, format, &value);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string const buffer(token.start, token.end);
|
||||
count = sscanf(buffer.c_str(), format, &value);
|
||||
}
|
||||
if (count != 1)
|
||||
auto const [ptr, ec] = std::from_chars(token.start, token.end, value);
|
||||
|
||||
// Reject anything from_chars could not turn into a finite double:
|
||||
// - ec != std::errc{}: no valid conversion, or an out-of-range magnitude
|
||||
// (e.g. 1e400).
|
||||
// - ptr != token.end: readNumber() is permissive about which characters
|
||||
// it collects into a token (it will, for example, keep a '+' mid-token),
|
||||
// but from_chars() will stop at the first character it cannot parse.
|
||||
if (ec != std::errc{} || ptr != token.end)
|
||||
return addError("'" + std::string(token.start, token.end) + "' is not a number.", token);
|
||||
|
||||
currentValue() = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ public:
|
||||
if (length == kUnknown)
|
||||
length = (value != nullptr) ? (unsigned int)strlen(value) : 0;
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
|
||||
char* newString = static_cast<char*>(malloc(length + 1));
|
||||
if (value != nullptr)
|
||||
memcpy(newString, value, length);
|
||||
@@ -59,7 +60,10 @@ public:
|
||||
releaseStringValue(char* value) override
|
||||
{
|
||||
if (value != nullptr)
|
||||
{
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
|
||||
free(value);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -120,7 +124,10 @@ Value::CZString::CZString(CZString const& other)
|
||||
Value::CZString::~CZString()
|
||||
{
|
||||
if ((cstr_ != nullptr) && index_ == static_cast<int>(DuplicationPolicy::Duplicate))
|
||||
{
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
|
||||
valueAllocator()->releaseMemberName(const_cast<char*>(cstr_));
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -241,6 +248,7 @@ Value::Value(std::string const& value) : type_(ValueType::String), allocated_(tr
|
||||
|
||||
Value::Value(StaticString const& value) : type_(ValueType::String)
|
||||
{
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
|
||||
value_.stringVal = const_cast<char*>(value.cStr());
|
||||
}
|
||||
|
||||
|
||||
@@ -4,13 +4,14 @@
|
||||
#include <xrpl/json/json_forwards.h>
|
||||
#include <xrpl/json/json_value.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <charconv>
|
||||
#include <cstring>
|
||||
#include <iomanip>
|
||||
#include <ios>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
#include <utility>
|
||||
|
||||
namespace json {
|
||||
@@ -76,19 +77,18 @@ valueToString(UInt value)
|
||||
std::string
|
||||
valueToString(double value)
|
||||
{
|
||||
// Allocate a buffer that is more than large enough to store the 16 digits
|
||||
// of precision requested below.
|
||||
// Format with 16 significant digits.
|
||||
// We need not request the alternative representation that always has a
|
||||
// decimal point because JSON doesn't distinguish the concepts of reals and integers.
|
||||
// A double never needs more than 32 characters in this form,
|
||||
// so to_chars cannot actually run out of room here.
|
||||
char buffer[32];
|
||||
// Print into the buffer. We need not request the alternative representation
|
||||
// that always has a decimal point because JSON doesn't distinguish the
|
||||
// concepts of reals and integers.
|
||||
#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with visual studio 2005
|
||||
// to avoid warning.
|
||||
sprintf_s(buffer, sizeof(buffer), "%.16g", value);
|
||||
#else
|
||||
snprintf(buffer, sizeof(buffer), "%.16g", value);
|
||||
#endif
|
||||
return buffer;
|
||||
auto const [ptr, ec] =
|
||||
std::to_chars(buffer, buffer + sizeof(buffer), value, std::chars_format::general, 16);
|
||||
XRPL_ASSERT(ec == std::errc{}, "json::valueToString(double) : conversion fits buffer");
|
||||
if (ec != std::errc{})
|
||||
return {};
|
||||
return std::string(buffer, ptr);
|
||||
}
|
||||
|
||||
std::string
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace xrpl::NodeStore {
|
||||
|
||||
DecodedBlob::DecodedBlob(void const* key, void const* value, int valueBytes)
|
||||
DecodedBlob::DecodedBlob(void const* key, void const* value, int valueBytes) : key_(key)
|
||||
{
|
||||
/* Data format:
|
||||
|
||||
@@ -23,10 +23,6 @@ DecodedBlob::DecodedBlob(void const* key, void const* value, int valueBytes)
|
||||
9...end The body of the object data
|
||||
*/
|
||||
|
||||
success_ = false;
|
||||
key_ = key;
|
||||
objectType_ = NodeObjectType::Unknown;
|
||||
objectData_ = nullptr;
|
||||
dataBytes_ = std::max(0, valueBytes - 9);
|
||||
|
||||
// VFALCO NOTE What about bytes 4 through 7 inclusive?
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace {
|
||||
//------------------------------------------------------------------------------
|
||||
// clang-format off
|
||||
// NOLINTNEXTLINE(readability-identifier-naming)
|
||||
char const* const versionString = "3.3.0-b0"
|
||||
char const* const versionString = "3.3.0-b1"
|
||||
// clang-format on
|
||||
;
|
||||
|
||||
|
||||
@@ -152,7 +152,12 @@ std::uint64_t
|
||||
getQuality(uint256 const& uBase)
|
||||
{
|
||||
// VFALCO [base_uint] This assumes a certain storage format
|
||||
return boost::endian::big_to_native(((std::uint64_t*)uBase.end())[-1]);
|
||||
//
|
||||
// Load the final 8 bytes as a big-endian integer. load_big_u64 reads
|
||||
// through unaligned byte storage (via memcpy) and applies the endian
|
||||
// conversion, avoiding the alignment/strict-aliasing UB of casting the
|
||||
// unsigned char* returned by end() to a std::uint64_t*.
|
||||
return boost::endian::load_big_u64(uBase.end() - 8);
|
||||
}
|
||||
|
||||
uint256
|
||||
@@ -278,8 +283,11 @@ quality(Keylet const& k, std::uint64_t q) noexcept
|
||||
// for indexes.
|
||||
uint256 x = k.key;
|
||||
|
||||
// FIXME This is ugly and we can and should do better...
|
||||
((std::uint64_t*)x.end())[-1] = boost::endian::native_to_big(q);
|
||||
// Store the quality as a big-endian integer in the final 8 bytes.
|
||||
// store_big_u64 writes through unaligned byte storage (via memcpy) and
|
||||
// applies the endian conversion, avoiding the alignment/strict-aliasing UB
|
||||
// of casting the unsigned char* returned by end() to a std::uint64_t*.
|
||||
boost::endian::store_big_u64(x.end() - 8, q);
|
||||
|
||||
return {ltDIR_NODE, x};
|
||||
}
|
||||
|
||||
@@ -21,11 +21,12 @@ SOTemplate::SOTemplate(
|
||||
}
|
||||
|
||||
SOTemplate::SOTemplate(std::vector<SOElement> uniqueFields, std::vector<SOElement> commonFields)
|
||||
: indices_(SField::getNumFields() + 1, -1) // Unmapped indices == -1
|
||||
: elements_(std::move(uniqueFields))
|
||||
, indices_(SField::getNumFields() + 1, -1) // Unmapped indices == -1
|
||||
{
|
||||
// Add all SOElements.
|
||||
//
|
||||
elements_ = std::move(uniqueFields);
|
||||
|
||||
std::ranges::move(commonFields, std::back_inserter(elements_));
|
||||
|
||||
// Validate and index elements_.
|
||||
|
||||
@@ -69,6 +69,17 @@ toUnsigned(U2 value)
|
||||
return static_cast<U1>(value);
|
||||
}
|
||||
|
||||
static std::string
|
||||
joinName(std::string const& jsonName, std::string const& fieldName)
|
||||
{
|
||||
std::string result;
|
||||
result.reserve(jsonName.size() + 1 + fieldName.size());
|
||||
result += jsonName;
|
||||
result += '.';
|
||||
result += fieldName;
|
||||
return result;
|
||||
}
|
||||
|
||||
// LCOV_EXCL_START
|
||||
static inline std::string
|
||||
makeName(std::string const& object, std::string const& field)
|
||||
@@ -76,7 +87,7 @@ makeName(std::string const& object, std::string const& field)
|
||||
if (field.empty())
|
||||
return object;
|
||||
|
||||
return object + "." + field;
|
||||
return joinName(object, field);
|
||||
}
|
||||
|
||||
static inline json::Value
|
||||
@@ -1036,8 +1047,8 @@ parseObject(
|
||||
|
||||
try
|
||||
{
|
||||
auto ret =
|
||||
parseObject(jsonName + "." + fieldName, value, field, depth + 1, error);
|
||||
auto ret = parseObject(
|
||||
joinName(jsonName, fieldName), value, field, depth + 1, error);
|
||||
if (!ret)
|
||||
return std::nullopt;
|
||||
data.emplaceBack(std::move(*ret));
|
||||
@@ -1054,8 +1065,8 @@ parseObject(
|
||||
case STI_ARRAY:
|
||||
try
|
||||
{
|
||||
auto array =
|
||||
parseArray(jsonName + "." + fieldName, value, field, depth + 1, error);
|
||||
auto array = parseArray(
|
||||
joinName(jsonName, fieldName), value, field, depth + 1, error);
|
||||
if (!array.has_value())
|
||||
return std::nullopt;
|
||||
data.emplaceBack(std::move(*array));
|
||||
|
||||
@@ -66,9 +66,9 @@ getTxFormat(TxType type)
|
||||
return format;
|
||||
}
|
||||
|
||||
STTx::STTx(STObject&& object) : STObject(std::move(object))
|
||||
STTx::STTx(STObject&& object)
|
||||
: STObject(std::move(object)), txType_(safeCast<TxType>(getFieldU16(sfTransactionType)))
|
||||
{
|
||||
txType_ = safeCast<TxType>(getFieldU16(sfTransactionType));
|
||||
applyTemplate(getTxFormat(txType_)->getSOTemplate()); // may throw
|
||||
tid_ = getHash(HashPrefix::TransactionId);
|
||||
buildBatchTxnIds();
|
||||
@@ -100,6 +100,9 @@ STTx::STTx(TxType type, std::function<void(STObject&)> assembler) : STObject(sfT
|
||||
|
||||
assembler(*this);
|
||||
|
||||
// txType_ must be read after the object is assembled, so this cannot be a
|
||||
// member initializer.
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer)
|
||||
txType_ = safeCast<TxType>(getFieldU16(sfTransactionType));
|
||||
|
||||
if (txType_ != type)
|
||||
|
||||
@@ -99,7 +99,7 @@ int
|
||||
Serializer::addRaw(void const* ptr, int len)
|
||||
{
|
||||
int const ret = data_.size();
|
||||
data_.insert(data_.end(), (char const*)ptr, ((char const*)ptr) + len);
|
||||
data_.insert(data_.end(), static_cast<char const*>(ptr), static_cast<char const*>(ptr) + len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,16 +23,16 @@
|
||||
namespace xrpl {
|
||||
|
||||
TxMeta::TxMeta(uint256 const& txid, std::uint32_t ledger, STObject const& obj)
|
||||
: transactionID_(txid), ledgerSeq_(ledger), nodes_(obj.getFieldArray(sfAffectedNodes))
|
||||
: transactionID_(txid)
|
||||
, ledgerSeq_(ledger)
|
||||
, index_(obj.getFieldU32(sfTransactionIndex))
|
||||
, result_(obj.getFieldU8(sfTransactionResult))
|
||||
, nodes_([&obj] {
|
||||
auto const affectedNodes = dynamic_cast<STArray const*>(obj.peekAtPField(sfAffectedNodes));
|
||||
XRPL_ASSERT(affectedNodes, "xrpl::TxMeta::TxMeta(STObject) : type cast succeeded");
|
||||
return affectedNodes != nullptr ? *affectedNodes : obj.getFieldArray(sfAffectedNodes);
|
||||
}())
|
||||
{
|
||||
result_ = obj.getFieldU8(sfTransactionResult);
|
||||
index_ = obj.getFieldU32(sfTransactionIndex);
|
||||
|
||||
auto affectedNodes = dynamic_cast<STArray const*>(obj.peekAtPField(sfAffectedNodes));
|
||||
XRPL_ASSERT(affectedNodes, "xrpl::TxMeta::TxMeta(STObject) : type cast succeeded");
|
||||
if (affectedNodes != nullptr)
|
||||
nodes_ = *affectedNodes;
|
||||
|
||||
setAdditionalFields(obj);
|
||||
}
|
||||
|
||||
|
||||
@@ -213,6 +213,12 @@ public:
|
||||
if (auto [conn, keepAlive] = getConnection(); conn)
|
||||
{
|
||||
(void)keepAlive;
|
||||
// The checkpointer is identified to the C callback by an integer id
|
||||
// (resolved via checkpointerFromId) rather than a raw `this`, so it
|
||||
// cannot dangle if the checkpointer is destroyed. Passing the id
|
||||
// through sqlite's void* user-data requires an integer-to-pointer
|
||||
// cast.
|
||||
// NOLINTNEXTLINE(performance-no-int-to-ptr)
|
||||
sqlite_api::sqlite3_wal_hook(conn, &sqliteWALHook, reinterpret_cast<void*>(id_));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -838,6 +838,7 @@ SHAMap::getHash() const
|
||||
auto hash = root_->getHash();
|
||||
if (hash.isZero())
|
||||
{
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
|
||||
const_cast<SHAMap&>(*this).unshare();
|
||||
hash = root_->getHash();
|
||||
}
|
||||
|
||||
@@ -1157,7 +1157,11 @@ toClaim(STTx const& tx)
|
||||
|
||||
try
|
||||
{
|
||||
STObject o{tx};
|
||||
// Copy just the field bag out of the transaction (explicitly, via the
|
||||
// STObject base) so it can be reinterpreted as a cross-chain attestation
|
||||
// below, with sfAccount replaced by sfOtherChainSource. STTx-specific
|
||||
// state (txType_, tid_) is intentionally not needed here.
|
||||
STObject o{static_cast<STObject const&>(tx)};
|
||||
o.setAccountID(sfAccount, o[sfOtherChainSource]);
|
||||
return TAttestation(o);
|
||||
}
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <initializer_list>
|
||||
#include <optional>
|
||||
#include <stdexcept>
|
||||
@@ -309,31 +308,26 @@ struct ExistingElementPool
|
||||
currencyNames.clear();
|
||||
currencyNames.reserve(numCur);
|
||||
|
||||
static constexpr size_t kBufSize = 32;
|
||||
char buf[kBufSize];
|
||||
|
||||
for (size_t id = 0; id < numAct; ++id)
|
||||
{
|
||||
snprintf(buf, kBufSize, "A%zu", id);
|
||||
accounts.emplace_back(buf);
|
||||
}
|
||||
accounts.emplace_back("A" + std::to_string(id));
|
||||
|
||||
for (size_t id = 0; id < numCur; ++id)
|
||||
{
|
||||
std::string name;
|
||||
if (id < 10)
|
||||
{
|
||||
snprintf(buf, kBufSize, "CC%zu", id);
|
||||
name = "CC" + std::to_string(id);
|
||||
}
|
||||
else if (id < 100)
|
||||
{
|
||||
snprintf(buf, kBufSize, "C%zu", id);
|
||||
name = "C" + std::to_string(id);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(buf, kBufSize, "%zu", id);
|
||||
name = std::to_string(id);
|
||||
}
|
||||
currencies.emplace_back(toCurrency(buf));
|
||||
currencyNames.emplace_back(buf);
|
||||
currencies.emplace_back(toCurrency(name));
|
||||
currencyNames.emplace_back(name);
|
||||
}
|
||||
|
||||
for (auto const& a : accounts)
|
||||
|
||||
@@ -245,9 +245,9 @@ struct Balance
|
||||
T& env;
|
||||
STAmount startAmount;
|
||||
|
||||
Balance(T& env, jtx::Account const& account) : account(account), env(env)
|
||||
Balance(T& env, jtx::Account const& account)
|
||||
: account(account), env(env), startAmount(env.balance(account))
|
||||
{
|
||||
startAmount = env.balance(account);
|
||||
}
|
||||
|
||||
[[nodiscard]] STAmount
|
||||
|
||||
@@ -1475,6 +1475,7 @@ r.ripple.com:51235
|
||||
std::string toLoad(R"xrpldConfig(
|
||||
[amendment_majority_time]
|
||||
)xrpldConfig");
|
||||
// NOLINTNEXTLINE(performance-inefficient-string-concatenation)
|
||||
toLoad += std::to_string(val) + space + unit;
|
||||
space = space.empty() ? " " : "";
|
||||
|
||||
|
||||
@@ -135,9 +135,8 @@ class PowerLawDistribution
|
||||
public:
|
||||
using result_type = double;
|
||||
|
||||
PowerLawDistribution(double xmin, double a) : xmin_{xmin}, a_{a}
|
||||
PowerLawDistribution(double xmin, double a) : xmin_{xmin}, a_{a}, inv_(1.0 / (1.0 - a_))
|
||||
{
|
||||
inv_ = 1.0 / (1.0 - a_);
|
||||
}
|
||||
|
||||
template <class Generator>
|
||||
|
||||
@@ -323,12 +323,11 @@ class Validator
|
||||
using Links = std::unordered_map<Peer::id_t, LinkSPtr>;
|
||||
|
||||
public:
|
||||
Validator() : pkey_(std::get<0>(randomKeyPair(KeyType::Ed25519)))
|
||||
Validator() : pkey_(std::get<0>(randomKeyPair(KeyType::Ed25519))), id_(sid++)
|
||||
{
|
||||
protocol::TMValidation v;
|
||||
v.set_validation("validation");
|
||||
message_ = std::make_shared<Message>(v, protocol::mtVALIDATION, pkey_);
|
||||
id_ = sid++;
|
||||
}
|
||||
Validator(Validator const&) = default;
|
||||
Validator(Validator&&) = default;
|
||||
@@ -457,7 +456,6 @@ public:
|
||||
using id_t = Peer::id_t;
|
||||
PeerSim(Overlay& overlay, beast::Journal journal) : overlay_(overlay), squelch_(journal)
|
||||
{
|
||||
id_ = sid++;
|
||||
}
|
||||
|
||||
~PeerSim() override = default;
|
||||
@@ -512,7 +510,7 @@ public:
|
||||
private:
|
||||
inline static id_t sid = 0;
|
||||
std::string fingerprint_;
|
||||
id_t id_;
|
||||
id_t id_{sid++};
|
||||
Overlay& overlay_;
|
||||
reduce_relay::Squelch<ManualClock> squelch_;
|
||||
};
|
||||
|
||||
@@ -1366,6 +1366,7 @@ public:
|
||||
{
|
||||
fail("Unable to build object from json");
|
||||
}
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-slicing)
|
||||
else if (STObject(j) != parsed.object)
|
||||
{
|
||||
log << "ORIG: " << j.getJson(JsonOptions::Values::None) << '\n'
|
||||
|
||||
@@ -80,7 +80,9 @@ TxTest::TxTest(std::optional<FeatureBitset> features)
|
||||
std::vector<uint256>{featureSet_.begin(), featureSet_.end()},
|
||||
registry_.getNodeFamily());
|
||||
|
||||
// Initialize time from the genesis ledger
|
||||
// Initialize time from the genesis ledger. closedLedger_ is created above
|
||||
// in the body, so this cannot be a member initializer.
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer)
|
||||
now_ = closedLedger_->header().closeTime;
|
||||
|
||||
// Create an open view on top of the genesis ledger
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <exception>
|
||||
#include <limits>
|
||||
#include <numbers>
|
||||
#include <optional>
|
||||
#include <regex>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
@@ -592,6 +593,57 @@ TEST(json_value, bad_json)
|
||||
EXPECT_TRUE(r.parse(s, j));
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
std::optional<json::Value>
|
||||
parseValue(std::string const& doc)
|
||||
{
|
||||
json::Value j;
|
||||
json::Reader r;
|
||||
if (!r.parse("{\"v\":" + doc + "}", j))
|
||||
return std::nullopt;
|
||||
return j["v"];
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(json_value, parse_double_valid)
|
||||
{
|
||||
// 1e300 is large but still representable, so it parses (unlike the out-of-range cases below).
|
||||
for (auto const& [text, expected] :
|
||||
{std::pair{"2.5", 2.5},
|
||||
std::pair{"-3.25e2", -325.0},
|
||||
std::pair{"0.0", 0.0},
|
||||
std::pair{"1E3", 1000.0},
|
||||
std::pair{"-0.5e-1", -0.05},
|
||||
std::pair{"1e300", 1e300}})
|
||||
{
|
||||
auto const v = parseValue(text);
|
||||
ASSERT_TRUE(v.has_value()) << text;
|
||||
// NOLINTBEGIN(bugprone-unchecked-optional-access)
|
||||
EXPECT_TRUE(v->isDouble()) << text;
|
||||
EXPECT_EQ(v->asDouble(), expected) << text;
|
||||
// NOLINTEND(bugprone-unchecked-optional-access)
|
||||
}
|
||||
}
|
||||
|
||||
TEST(json_value, parse_double_out_of_range)
|
||||
{
|
||||
// Magnitudes with no finite double representation are rejected.
|
||||
for (char const* oor : {"1e400", "-1e400", "0.001e500", "1e-400", "-1e-400", "123e-500"})
|
||||
EXPECT_FALSE(parseValue(oor).has_value()) << oor;
|
||||
}
|
||||
|
||||
TEST(json_value, parse_double_malformed)
|
||||
{
|
||||
// readNumber() collects any run of digits and '.eE+-' into a single Double
|
||||
// token, so these malformed tokens reach decodeDouble. Each has a valid
|
||||
// leading prefix that from_chars would accept on its own; requiring the
|
||||
// entire token be consumed rejects them instead of silently truncating.
|
||||
for (char const* bad : {"1+2", "1-2", "1.2.3", "1e5e6", "1..2", "++5", "1e", "1e+", ".", "-"})
|
||||
EXPECT_FALSE(parseValue(bad).has_value()) << bad;
|
||||
}
|
||||
|
||||
TEST(json_value, edge_cases)
|
||||
{
|
||||
std::uint32_t const maxUInt = std::numeric_limits<std::uint32_t>::max();
|
||||
|
||||
@@ -643,6 +643,7 @@ AmendmentState*
|
||||
AmendmentTableImpl::get(uint256 const& amendmentHash, std::scoped_lock<std::mutex> const& lock)
|
||||
{
|
||||
// Forward to the const version of get.
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
|
||||
return const_cast<AmendmentState*>(std::as_const(*this).get(amendmentHash, lock));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user