Compare commits

..

69 Commits

Author SHA1 Message Date
Bart
228ad1e98f Fix clang-tidy findings 2026-03-31 17:33:15 -04:00
Bart
c4b342a027 Merge branch 'develop' into bthomee/node_depth 2026-03-31 17:12:43 -04:00
Bart
556d80e724 Fix clang-tidy findings 2026-03-31 16:31:24 -04:00
Mayukha Vadari
a9afd2c116 fix: Fix previous ledger size typo in RCLConsensus (#6696) 2026-03-31 19:56:30 +00:00
Bart
044f1e67b9 Merge branch 'develop' into bthomee/node_depth 2026-03-31 14:00:34 -04:00
Alex Kremer
2502befb42 chore: Enable clang-tidy misc checks (#6655) 2026-03-31 17:29:45 +00:00
Ayaz Salikhov
c3fae847f3 ci: Use pull_request_target to check for signed commits (#6697) 2026-03-31 17:14:41 +00:00
Bart
7f53351920 chore: Remove unnecessary clang-format off/on directives (#6682)
Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com>
2026-03-31 15:38:04 +00:00
Pratik Mankawde
bb95a7d6cd fix: Fix Workers::stop() race between m_allPaused and m_runningTaskCount (#6574)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-31 15:06:04 +00:00
Ayaz Salikhov
5c8dfe5456 ci: Only publish docs in public repos (#6687) 2026-03-30 17:15:40 +00:00
Alex Kremer
ab8c168e3b chore: Enable remaining clang-tidy performance checks (#6648)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-30 17:08:47 +00:00
Jingchen
3a477e4d01 refactor: Address PR comments after the modularisation PRs (#6389)
Signed-off-by: JCW <a1q123456@users.noreply.github.com>
Co-authored-by: Bart <bthomee@users.noreply.github.com>
2026-03-30 15:22:38 +00:00
Alex Kremer
96bfc32fe2 chore: Fix clang-tidy header filter (#6686) 2026-03-30 14:59:53 +00:00
dependabot[bot]
de671863e2 ci: [DEPENDABOT] bump actions/deploy-pages from 4.0.5 to 5.0.0 (#6684)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-30 14:09:57 +00:00
dependabot[bot]
e0cabb9f8c ci: [DEPENDABOT] bump codecov/codecov-action from 5.5.3 to 6.0.0 (#6685)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-30 13:57:32 +00:00
Pratik Mankawde
3d9c545f59 fix: Guard Coro::resume() against completed coroutines (#6608)
Signed-off-by: Pratik Mankawde <3397372+pratikmankawde@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-27 18:52:18 +00:00
Vito Tumas
9b944ee8c2 refactor: Split LoanInvariant into LoanBrokerInvariant and LoanInvariant (#6674) 2026-03-27 18:35:42 +00:00
Ayaz Salikhov
509677abfd ci: Don't publish docs on release branches (#6673) 2026-03-26 14:11:37 +00:00
Jingchen
addc1e8e25 refactor: Make function naming in ServiceRegistry consistent (#6390)
Signed-off-by: JCW <a1q123456@users.noreply.github.com>
Co-authored-by: Ed Hennis <ed@ripple.com>
2026-03-26 14:11:16 +00:00
Valentin Balaschenko
faf69da4b0 chore: Shorten job names to stay within Linux 15-char thread limit (#6669) 2026-03-26 14:10:51 +00:00
Vito Tumas
76e3b4fb0f fix: Improve loan invariant message (#6668) 2026-03-26 12:40:26 +00:00
Ayaz Salikhov
e8bdbf975a ci: Upload artifacts only in public repositories (#6670) 2026-03-26 12:37:37 +00:00
Bart
0ad72fae8f Merge branch 'develop' into bthomee/node_depth 2026-03-22 06:33:02 -04:00
Bart
cc383c5fb8 Clang-tidy fixes 2026-03-18 15:09:46 -04:00
Bart
88715f1e5a Merge branch 'develop' into bthomee/node_depth 2026-03-18 13:38:55 -04:00
Bart
e1477cef0c Fix merge conflict 2026-03-18 09:56:08 -04:00
Bart
942874d7b0 Merge branch 'develop' into bthomee/node_depth 2026-03-18 09:47:16 -04:00
Bart
79326fc6b5 Merge branch 'develop' into bthomee/node_depth 2026-03-16 19:48:17 -04:00
Bart
48535d5226 Merge branch 'develop' into bthomee/node_depth 2026-03-10 17:11:14 +01:00
Bart
d1a6558080 Merge branch 'develop' into bthomee/node_depth 2026-03-10 15:39:32 +01:00
Bart
84f86b354f Add defensive check 2026-03-06 13:28:39 +01:00
Bart
40a3985b02 Merge branch 'develop' into bthomee/node_depth 2026-03-06 09:27:59 +01:00
Bart
208bd35d45 Merge branch 'develop' into bthomee/node_depth 2026-03-05 08:36:13 +01:00
Bart
e90fbbf7b2 Copilot review feedback 2026-03-02 13:39:29 -05:00
Bart
277450e648 Merge branch 'develop' into bthomee/node_depth 2026-03-02 12:16:33 -05:00
Bart
e6993524ea Copilot review feedback 2026-03-02 12:10:12 -05:00
Bart
b117ecc6a2 Use std::string_view 2026-03-02 11:58:57 -05:00
Bart
6c3b00c342 Change takeNodes vector argument to r-value 2026-03-02 09:41:23 -05:00
Bart
8c296a935a Improve docstring 2026-03-01 17:44:48 -05:00
Bart
573ba82181 Copilot review feedback 2026-03-01 17:33:03 -05:00
Bart
1542ab7e27 Copilot review feedback 2026-03-01 17:04:04 -05:00
Bart
6374f4886d Support leaf nodes at depth 0, use std::move, simplify tests 2026-03-01 16:44:58 -05:00
Bart
ebf336f472 Copilot review feedback 2026-03-01 15:10:57 -05:00
Bart
ddc15ad612 Copilot review feedback 2026-03-01 14:48:27 -05:00
Bart
82db6ac498 Restore try-catch to protect against other exceptions 2026-03-01 13:33:39 -05:00
Bart
f749c41306 Add log message for consistency 2026-02-28 17:31:22 -05:00
Bart
f25e47a58d Improve comment 2026-02-28 17:27:15 -05:00
Bart
2396799bd8 Update levelization 2026-02-28 16:03:02 -05:00
Bart
4855b9f96a Improve function docstrings, fix tests 2026-02-28 15:46:49 -05:00
Bart
b2f65cb7eb Fix protocol version test 2026-02-28 14:40:55 -05:00
Bart
c523673885 Update levelization 2026-02-28 14:00:13 -05:00
Bart
caac4d63d3 Merge branch 'develop' into bthomee/node_depth 2026-02-28 13:56:37 -05:00
Bart
29b0076fa8 Use new protocol version instead of amendment, add tests 2026-02-28 13:54:00 -05:00
Bart
c9aa1094a7 Update docstrings 2026-02-27 12:55:14 -05:00
Bart
b86f69cb82 Merge branch 'develop' into bthomee/node_depth 2026-02-26 17:33:25 -05:00
Bart
5d0bf78512 Clang-format to 100 line length 2026-02-26 17:09:20 -05:00
Bart
554df631c6 Remove pragma once 2026-02-18 08:28:56 -05:00
Bart
5e704bfdfb Merge branch 'develop' into bthomee/node_depth 2026-02-18 08:02:52 -05:00
Bart
fe8cc02bfa Refine 2026-02-18 07:54:33 -05:00
Bart
061c033f52 Use oneof in proto message 2026-02-16 16:50:40 -05:00
Bart
832a7e7e4a Remove depth, do not include node ID for leaf nodes 2026-02-13 17:05:05 -05:00
Bart
b2371c4c02 Fixes 2026-02-13 15:47:08 -05:00
Bart
b94a7c4b44 Merge branch 'develop' into bthomee/node_depth 2026-02-13 11:46:56 -05:00
Bart
9b9027112d Use helper functions 2026-02-13 11:44:58 -05:00
Bart
8e7889c66e Refactor 2026-02-12 16:55:38 -05:00
Bart
d836c3788d Merge branch 'develop' into bthomee/node_depth 2026-02-12 15:33:13 -05:00
Bart
1cb7c0293f Check if amendment is enabled 2026-02-12 06:31:32 -05:00
Bart
52dabc1f79 Remove deprecated stanza on nodeid field 2026-02-11 16:28:35 -05:00
Bart
2d78d41f7b perf: Replace node ID by depth in TMLedgerNode 2026-02-11 15:55:16 -05:00
144 changed files with 1159 additions and 599 deletions

View File

@@ -78,14 +78,14 @@ Checks: "-*,
bugprone-unused-return-value,
bugprone-unused-local-non-trivial-variable,
bugprone-virtual-near-miss,
cppcoreguidelines-init-variables,
cppcoreguidelines-misleading-capture-default-by-value,
# cppcoreguidelines-init-variables, # has issues
# cppcoreguidelines-misleading-capture-default-by-value, # has issues
cppcoreguidelines-no-suspend-with-lock,
cppcoreguidelines-pro-type-member-init,
# cppcoreguidelines-pro-type-member-init, # has issues
cppcoreguidelines-pro-type-static-cast-downcast,
cppcoreguidelines-rvalue-reference-param-not-moved,
cppcoreguidelines-use-default-member-init,
cppcoreguidelines-virtual-class-destructor,
# cppcoreguidelines-rvalue-reference-param-not-moved, # has issues
# cppcoreguidelines-use-default-member-init, # has issues
# cppcoreguidelines-virtual-class-destructor, # has issues
hicpp-ignored-remove-result,
misc-const-correctness,
misc-definitions-in-headers,

View File

@@ -44,6 +44,7 @@ libxrpl.tx > xrpl.server
libxrpl.tx > xrpl.tx
test.app > test.jtx
test.app > test.rpc
test.app > test.shamap
test.app > test.toplevel
test.app > test.unit_test
test.app > xrpl.basics
@@ -59,6 +60,7 @@ test.app > xrpl.protocol
test.app > xrpl.rdb
test.app > xrpl.resource
test.app > xrpl.server
test.app > xrpl.shamap
test.app > xrpl.tx
test.basics > test.jtx
test.basics > test.unit_test

View File

@@ -36,7 +36,7 @@ env:
BUILD_DIR: build
# ubuntu-latest has only 2 CPUs for private repositories
# https://docs.github.com/en/actions/reference/runners/github-hosted-runners#standard-github-hosted-runners-for--private-repositories
NPROC_SUBTRACT: ${{ github.event.repository.visibility == 'public' && '2' || '1' }}
NPROC_SUBTRACT: ${{ github.event.repository.private && '1' || '2' }}
jobs:
build:
@@ -81,13 +81,13 @@ jobs:
cmake --build . --target docs --parallel ${BUILD_NPROC}
- name: Create documentation artifact
if: ${{ (github.repository_owner == 'XRPLF' || github.event.repository.visibility == 'public') && github.event_name == 'push' }}
if: ${{ github.event.repository.visibility == 'public' && github.event_name == 'push' }}
uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0
with:
path: ${{ env.BUILD_DIR }}/docs/html
deploy:
if: ${{ (github.repository_owner == 'XRPLF' || github.event.repository.visibility == 'public') && github.event_name == 'push' }}
if: ${{ github.event.repository.visibility == 'public' && github.event_name == 'push' }}
needs: build
runs-on: ubuntu-latest
permissions:

View File

@@ -199,7 +199,7 @@ jobs:
fi
- name: Upload the binary (Linux)
if: ${{ (github.repository_owner == 'XRPLF' || github.event.repository.visibility == 'public') && runner.os == 'Linux' }}
if: ${{ github.event.repository.visibility == 'public' && runner.os == 'Linux' }}
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: xrpld-${{ inputs.config_name }}

View File

@@ -83,7 +83,7 @@ jobs:
run-clang-tidy -j ${{ steps.nproc.outputs.nproc }} -p "${BUILD_DIR}" -quiet -allow-no-checks ${TARGETS} 2>&1 | tee clang-tidy-output.txt
- name: Upload clang-tidy output
if: ${{ (github.repository_owner == 'XRPLF' || github.event.repository.visibility == 'public') && steps.run_clang_tidy.outcome != 'success' }}
if: ${{ github.event.repository.visibility == 'public' && steps.run_clang_tidy.outcome != 'success' }}
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: clang-tidy-results

View File

@@ -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' 'grpc' 'm4' 'mpt-crypto' 'nudb' 'openssl' 'secp256k1' 'snappy' 'soci' 'wasm-xrplf' 'wasmi')
# Selectively check out the recipes from our CCI fork.
cd external

View File

@@ -3,22 +3,22 @@
"requires": [
"zlib/1.3.1#cac0f6daea041b0ccf42934163defb20%1774439233.809",
"xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1765850149.987",
"sqlite3/3.51.0#66aa11eabd0e34954c5c1c061ad44abe%1774467355.988",
"sqlite3/3.51.0#66aa11eabd0e34954c5c1c061ad44abe%1763899256.358",
"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",
"protobuf/6.33.5#d96d52ba5baaaa532f47bda866ad87a5%1773224203.27",
"openssl/3.6.1#e6399de266349245a4542fc5f6c71552%1774458290.139",
"nudb/2.0.9#11149c73f8f2baff9a0198fe25971fc7%1774883011.384",
"nudb/2.0.9#0432758a24204da08fee953ec9ea03cb%1769436073.32",
"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",
"gtest/1.17.0#5224b3b3ff3b4ce1133cbdd27d53ee7d%1768312129.152",
"grpc/1.78.1#b1a9e74b145cc471bed4dc64dc6eb2c1%1774467387.342",
"grpc/1.78.1#b1a9e74b145cc471bed4dc64dc6eb2c1%1772623605.068",
"ed25519/2015.03#ae761bdc52730a843f0809bdf6c1b1f6%1765850143.772",
"date/3.0.4#862e11e80030356b53c2c38599ceb32b%1765850143.772",
"c-ares/1.34.6#545240bb1c40e2cacd4362d6b8967650%1774439234.681",
@@ -29,7 +29,7 @@
"build_requires": [
"zlib/1.3.1#cac0f6daea041b0ccf42934163defb20%1774439233.809",
"strawberryperl/5.32.1.1#8d114504d172cfea8ea1662d09b6333e%1774447376.964",
"protobuf/6.33.5#d96d52ba5baaaa532f47bda866ad87a5%1774467363.12",
"protobuf/6.33.5#d96d52ba5baaaa532f47bda866ad87a5%1773224203.27",
"nasm/2.16.01#31e26f2ee3c4346ecd347911bd126904%1765850144.707",
"msys2/cci.latest#d22fe7b2808f5fd34d0a7923ace9c54f%1770657326.649",
"m4/1.4.19#5d7a4994e5875d76faf7acf3ed056036%1774365463.87",
@@ -41,15 +41,16 @@
],
"python_requires": [],
"overrides": {
"boost/1.90.0#d5e8defe7355494953be18524a7f135b": [
null,
"boost/1.90.0"
],
"protobuf/[>=5.27.0 <7]": [
"protobuf/6.33.5"
],
"lz4/1.9.4": [
"lz4/1.10.0"
],
"boost/[>=1.83.0 <1.91.0]": [
"boost/1.90.0"
],
"sqlite3/[>=3.44 <4]": [
"sqlite3/3.51.0"
],

View File

@@ -34,7 +34,7 @@ public:
{
// Insert ourselves at the front of the lock-free linked list
CountedObjects& instance = CountedObjects::getInstance();
Counter* head = nullptr;
Counter* head;
do
{

View File

@@ -93,7 +93,7 @@ class DecayWindow
public:
using time_point = typename Clock::time_point;
explicit DecayWindow(time_point now) : when_(now)
explicit DecayWindow(time_point now) : value_(0), when_(now)
{
}
@@ -125,7 +125,7 @@ private:
when_ = now;
}
double value_{0};
double value_;
time_point when_;
};

View File

@@ -84,8 +84,7 @@ public:
template <class TT>
requires std::convertible_to<TT*, T*>
SharedIntrusive(
SharedIntrusive<TT>&& rhs); // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
SharedIntrusive(SharedIntrusive<TT>&& rhs);
SharedIntrusive&
operator=(SharedIntrusive const& rhs);
@@ -107,8 +106,7 @@ public:
template <class TT>
requires std::convertible_to<TT*, T*>
SharedIntrusive&
operator=(
SharedIntrusive<TT>&& rhs); // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
operator=(SharedIntrusive<TT>&& rhs);
/** Adopt the raw pointer. The strong reference may or may not be
incremented, depending on the TAdoptTag
@@ -316,8 +314,7 @@ public:
template <class TT>
requires std::convertible_to<TT*, T*>
SharedWeakUnion(
SharedIntrusive<TT>&& rhs); // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
SharedWeakUnion(SharedIntrusive<TT>&& rhs);
SharedWeakUnion&
operator=(SharedWeakUnion const& rhs);
@@ -330,8 +327,7 @@ public:
template <class TT>
requires std::convertible_to<TT*, T*>
SharedWeakUnion&
operator=(
SharedIntrusive<TT>&& rhs); // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
operator=(SharedIntrusive<TT>&& rhs);
~SharedWeakUnion();

View File

@@ -73,12 +73,12 @@ struct MantissaRange
enum mantissa_scale { small, large };
explicit constexpr MantissaRange(mantissa_scale scale_)
: min(getMin(scale_)), log(logTen(min).value_or(-1)), scale(scale_)
: min(getMin(scale_)), max(min * 10 - 1), log(logTen(min).value_or(-1)), scale(scale_)
{
}
rep min;
rep max{min * 10 - 1};
rep max;
int log;
mantissa_scale scale;

View File

@@ -91,7 +91,7 @@ class SlabAllocator
std::uint8_t*
allocate() noexcept
{
std::uint8_t* ret = nullptr; // NOLINT(misc-const-correctness)
std::uint8_t* ret;
{
std::lock_guard const l(m_);

View File

@@ -11,6 +11,7 @@
#include <limits>
#include <stdexcept>
#include <string>
#include <string_view>
#include <type_traits>
#include <vector>
@@ -231,4 +232,11 @@ makeSlice(std::basic_string<char, Traits, Alloc> const& s)
return Slice(s.data(), s.size());
}
template <class Traits>
Slice
makeSlice(std::basic_string_view<char, Traits> const& s)
{
return Slice(s.data(), s.size());
}
} // namespace xrpl

View File

@@ -182,7 +182,8 @@ private:
: hook(collector->make_hook(handler))
, size(collector->make_gauge(prefix, "size"))
, hit_rate(collector->make_gauge(prefix, "hit_rate"))
, hits(0)
, misses(0)
{
}
@@ -190,8 +191,8 @@ private:
beast::insight::Gauge size;
beast::insight::Gauge hit_rate;
std::size_t hits{0};
std::size_t misses{0};
std::size_t hits;
std::size_t misses;
};
class KeyOnlyEntry
@@ -293,10 +294,10 @@ private:
clock_type::duration const m_target_age;
// Number of items cached
int m_cache_count{0};
int m_cache_count;
cache_type m_cache; // Hold strong reference to recent objects
std::uint64_t m_hits{0};
std::uint64_t m_misses{0};
std::uint64_t m_hits;
std::uint64_t m_misses;
};
} // namespace xrpl

View File

@@ -36,7 +36,9 @@ inline TaggedCache<
, m_name(name)
, m_target_size(size)
, m_target_age(expiration)
, m_cache_count(0)
, m_hits(0)
, m_misses(0)
{
}

View File

@@ -335,13 +335,11 @@ public:
operator=(std::uint64_t uHost)
{
*this = beast::zero;
// NOLINTBEGIN(cppcoreguidelines-pro-type-member-init)
union
{
unsigned u[2];
std::uint64_t ul;
};
// NOLINTEND(cppcoreguidelines-pro-type-member-init)
// Put in least significant bits.
ul = boost::endian::native_to_big(uHost);
data_[WIDTH - 2] = u[0];
@@ -623,7 +621,7 @@ template <>
inline std::size_t
extract(uint256 const& key)
{
std::size_t result = 0;
std::size_t result;
// Use memcpy to avoid unaligned UB
// (will optimize to equivalent code)
std::memcpy(&result, key.data(), sizeof(std::size_t));

View File

@@ -58,7 +58,7 @@ default_prng()
// The thread-specific PRNGs:
thread_local beast::xor_shift_engine engine = [] {
std::uint64_t seed = 0;
std::uint64_t seed;
{
std::lock_guard const lk(m);
std::uniform_int_distribution<std::uint64_t> distribution{1};

View File

@@ -23,15 +23,15 @@ private:
std::recursive_mutex m_mutex;
std::condition_variable_any m_cond;
std::size_t m_count{1};
std::size_t m_count;
duration const m_period;
boost::asio::io_context& m_ios;
boost::asio::basic_waitable_timer<std::chrono::steady_clock> m_timer;
bool m_cancel{false};
bool m_cancel;
public:
io_latency_probe(duration const& period, boost::asio::io_context& ios)
: m_period(period), m_ios(ios), m_timer(m_ios)
: m_count(1), m_period(period), m_ios(ios), m_timer(m_ios), m_cancel(false)
{
}

View File

@@ -262,9 +262,7 @@ private:
{
}
config_t(
config_t&& other, // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
Allocator const& alloc)
config_t(config_t&& other, Allocator const& alloc)
: KeyValueCompare(std::move(other.key_compare()))
, beast::detail::empty_base_optimization<ElementAllocator>(alloc)
, clock(other.clock)
@@ -554,10 +552,7 @@ public:
aged_ordered_container(aged_ordered_container&& other);
aged_ordered_container(
// NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved)
aged_ordered_container&& other,
Allocator const& alloc);
aged_ordered_container(aged_ordered_container&& other, Allocator const& alloc);
aged_ordered_container(std::initializer_list<value_type> init, clock_type& clock);
@@ -1295,7 +1290,7 @@ aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::aged_
template <bool IsMulti, bool IsMap, class Key, class T, class Clock, class Compare, class Allocator>
aged_ordered_container<IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::aged_ordered_container(
aged_ordered_container&& other, // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
aged_ordered_container&& other,
Allocator const& alloc)
: m_config(std::move(other.m_config), alloc)
#if BOOST_VERSION >= 108000

View File

@@ -318,9 +318,7 @@ private:
{
}
config_t(
config_t&& other, // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
Allocator const& alloc)
config_t(config_t&& other, Allocator const& alloc)
: ValueHash(std::move(other.hash_function()))
, KeyValueEqual(std::move(other.key_eq()))
, beast::detail::empty_base_optimization<ElementAllocator>(alloc)
@@ -776,10 +774,7 @@ public:
aged_unordered_container(aged_unordered_container&& other);
aged_unordered_container(
// NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved)
aged_unordered_container&& other,
Allocator const& alloc);
aged_unordered_container(aged_unordered_container&& other, Allocator const& alloc);
aged_unordered_container(std::initializer_list<value_type> init, clock_type& clock);
@@ -1843,10 +1838,7 @@ template <
class KeyEqual,
class Allocator>
aged_unordered_container<IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::
aged_unordered_container(
// NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved)
aged_unordered_container&& other,
Allocator const& alloc)
aged_unordered_container(aged_unordered_container&& other, Allocator const& alloc)
: m_config(std::move(other.m_config), alloc)
, m_buck(alloc)
, m_cont(m_buck, std::cref(m_config.value_hash()), std::cref(m_config.key_value_equal()))

View File

@@ -187,7 +187,7 @@ public:
bool
push_front(Node* node)
{
bool first = false;
bool first;
Node* old_head = m_head.load(std::memory_order_relaxed);
do
{
@@ -211,7 +211,7 @@ public:
pop_front()
{
Node* node = m_head.load();
Node* new_head = nullptr;
Node* new_head;
do
{
if (node == &m_end)

View File

@@ -23,7 +23,7 @@ private:
// A 64-byte buffer should to be big enough for us
static constexpr std::size_t INTERNAL_BUFFER_SIZE = 64;
alignas(64) std::array<std::uint8_t, INTERNAL_BUFFER_SIZE> buffer_{};
alignas(64) std::array<std::uint8_t, INTERNAL_BUFFER_SIZE> buffer_;
std::span<std::uint8_t> readBuffer_;
std::span<std::uint8_t> writeBuffer_;

View File

@@ -35,10 +35,10 @@ private:
class tests_t : public detail::const_container<std::vector<test>>
{
private:
std::size_t failed_{0};
std::size_t failed_;
public:
tests_t()
tests_t() : failed_(0)
{
}
@@ -167,12 +167,12 @@ public:
class results : public detail::const_container<std::vector<suite_results>>
{
private:
std::size_t m_cases{0};
std::size_t total_{0};
std::size_t failed_{0};
std::size_t m_cases;
std::size_t total_;
std::size_t failed_;
public:
results()
results() : m_cases(0), total_(0), failed_(0)
{
}

View File

@@ -311,7 +311,7 @@ private:
std::string const m_name;
std::recursive_mutex lock_;
Item item_;
Source* parent_{nullptr};
Source* parent_;
List<Item> children_;
public:

View File

@@ -37,7 +37,7 @@ public:
}
private:
result_type s_[2]{};
result_type s_[2];
static result_type
murmurhash3(result_type x);

View File

@@ -92,9 +92,7 @@ private:
++counter_;
}
Substitute(
ClosureCounter& counter,
Closure&& closure) // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
Substitute(ClosureCounter& counter, Closure&& closure)
: counter_(counter), closure_(std::forward<Closure>(closure))
{
++counter_;

View File

@@ -7,6 +7,7 @@ JobQueue::Coro::Coro(Coro_create_t, JobQueue& jq, JobType type, std::string cons
: jq_(jq)
, type_(type)
, name_(name)
, running_(false)
, coro_(
// Stack size of 1MB wasn't sufficient for deep calls. ASAN tests flagged the issue. Hence
// increasing the size to 1.5MB.

View File

@@ -45,7 +45,7 @@ public:
JobQueue& jq_;
JobType type_;
std::string name_;
bool running_{false};
bool running_;
std::mutex mutex_;
std::mutex mutex_run_;
std::condition_variable cv_;
@@ -224,7 +224,7 @@ private:
beast::Journal m_journal;
mutable std::mutex m_mutex;
std::uint64_t m_lastJob{0};
std::uint64_t m_lastJob;
std::set<Job> m_jobSet;
JobCounter jobCounter_;
std::atomic_bool stopping_{false};
@@ -233,7 +233,7 @@ private:
JobTypeData m_invalidJobData;
// The number of jobs currently in processTask()
int m_processCount{0};
int m_processCount;
// The number of suspended coroutines
int nSuspend_ = 0;

View File

@@ -19,13 +19,13 @@ public:
JobTypeInfo const& info;
/* The number of jobs waiting */
int waiting{0};
int waiting;
/* The number presently running */
int running{0};
int running;
/* And the number we deferred executing because of job limits */
int deferred{0};
int deferred;
/* Notification callbacks */
beast::insight::Event dequeue;
@@ -35,8 +35,12 @@ public:
JobTypeInfo const& info_,
beast::insight::Collector::ptr const& collector,
Logs& logs) noexcept
: m_load(logs.journal("LoadMonitor")), m_collector(collector), info(info_)
: m_load(logs.journal("LoadMonitor"))
, m_collector(collector)
, info(info_)
, waiting(0)
, running(0)
, deferred(0)
{
m_load.setTargetLatency(info.getAverageLatency(), info.getPeakLatency());

View File

@@ -36,10 +36,10 @@ public:
{
Stats();
std::uint64_t count{0};
std::uint64_t count;
std::chrono::milliseconds latencyAvg;
std::chrono::milliseconds latencyPeak;
bool isOverloaded{false};
bool isOverloaded;
};
Stats
@@ -54,8 +54,8 @@ private:
std::mutex mutex_;
std::uint64_t mCounts{0};
int mLatencyEvents{0};
std::uint64_t mCounts;
int mLatencyEvents;
std::chrono::milliseconds mLatencyMSAvg;
std::chrono::milliseconds mLatencyMSPeak;
std::chrono::milliseconds mTargetLatencyAvg;

View File

@@ -92,7 +92,7 @@ public:
private:
beast::Journal mutable journal_;
std::mutex mutable mutex_;
DatabaseCon* connection_{};
DatabaseCon* connection_;
std::unordered_set<PeerReservation, beast::uhash<>, KeyEqual> table_;
};

View File

@@ -183,8 +183,8 @@ private:
std::thread thread_;
std::mutex mutex_;
std::condition_variable wakeup_;
int wakeCount_{0}; // how many times to un-pause
bool shouldExit_{false};
int wakeCount_; // how many times to un-pause
bool shouldExit_;
};
private:
@@ -197,9 +197,9 @@ private:
std::string m_threadNames; // The name to give each thread
std::condition_variable m_cv; // signaled when all threads paused
std::mutex m_mut;
bool m_allPaused{true};
bool m_allPaused;
semaphore m_semaphore; // each pending task is 1 resource
int m_numberOfThreads{0}; // how many we want active now
int m_numberOfThreads; // how many we want active now
std::atomic<int> m_activeCount; // to know when all are paused
std::atomic<int> m_pauseCount; // how many threads need to pause now
std::atomic<int> m_runningTaskCount; // how many calls to processTask() active

View File

@@ -103,9 +103,9 @@ private:
public:
explicit ErrorInfo() = default;
Token token_{};
Token token_;
std::string message_;
Location extra_{};
Location extra_;
};
using Errors = std::deque<ErrorInfo>;
@@ -173,11 +173,11 @@ private:
Nodes nodes_;
Errors errors_;
std::string document_;
Location begin_{};
Location end_{};
Location current_{};
Location lastValueEnd_{};
Value* lastValue_{};
Location begin_;
Location end_;
Location current_;
Location lastValueEnd_;
Value* lastValue_;
};
template <class BufferSequence>

View File

@@ -106,8 +106,8 @@ private:
ChildValues childValues_;
std::string document_;
std::string indentString_;
int rightMargin_{74};
int indentSize_{3};
int rightMargin_;
int indentSize_;
bool addChildValues_{};
};
@@ -171,9 +171,9 @@ private:
using ChildValues = std::vector<std::string>;
ChildValues childValues_;
std::ostream* document_{nullptr};
std::ostream* document_;
std::string indentString_;
int rightMargin_{74};
int rightMargin_;
std::string indentation_;
bool addChildValues_{};
};

View File

@@ -16,7 +16,7 @@ struct FetchReport
{
}
std::chrono::milliseconds elapsed{};
std::chrono::milliseconds elapsed;
FetchType const fetchType;
bool wasFound = false;
};

View File

@@ -71,8 +71,8 @@ private:
Scheduler& m_scheduler;
LockType mWriteMutex;
CondvarType mWriteCondition;
int mWriteLoad{0};
bool mWritePending{false};
int mWriteLoad;
bool mWritePending;
Batch mWriteSet;
};

View File

@@ -35,7 +35,7 @@ namespace NodeStore {
class EncodedBlob
{
/** The 32-byte key of the serialized object. */
std::array<std::uint8_t, 32> key_{};
std::array<std::uint8_t, 32> key_;
/** A pre-allocated buffer for the serialized object.
@@ -43,8 +43,7 @@ class EncodedBlob
1024 more bytes. The precise size is calculated automatically
at compile time so as to avoid wasting space on padding bytes.
*/
std::array<std::uint8_t, boost::alignment::align_up(9 + 1024, alignof(std::uint32_t))>
payload_{};
std::array<std::uint8_t, boost::alignment::align_up(9 + 1024, alignof(std::uint32_t))> payload_;
/** The size of the serialized data. */
std::uint32_t size_;

View File

@@ -56,7 +56,7 @@ lz4_compress(void const* in, std::size_t in_size, 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>::max> vi{};
std::array<std::uint8_t, varint_traits<std::size_t>::max> vi;
auto const n = write_varint(vi.data(), in_size);
auto const out_max = LZ4_compressBound(in_size);
std::uint8_t* out = reinterpret_cast<std::uint8_t*>(bf(n + out_max));
@@ -88,7 +88,7 @@ nodeobject_decompress(void const* in, std::size_t in_size, BufferFactory&& bf)
using namespace nudb::detail;
std::uint8_t const* p = reinterpret_cast<std::uint8_t const*>(in);
std::size_t type = 0;
std::size_t type;
auto const vn = read_varint(p, in_size, type);
if (vn == 0)
Throw<std::runtime_error>("nodeobject decompress");
@@ -117,7 +117,7 @@ nodeobject_decompress(void const* in, std::size_t in_size, BufferFactory&& bf)
"nodeobject codec v1: short inner node size: " + std::string("in_size = ") +
std::to_string(in_size) + " hs = " + std::to_string(hs));
istream is(p, in_size);
std::uint16_t mask = 0;
std::uint16_t mask;
read<std::uint16_t>(is, mask); // Mask
in_size -= hs;
result.second = 525;
@@ -196,10 +196,10 @@ nodeobject_compress(void const* in, std::size_t in_size, BufferFactory&& bf)
if (in_size == 525)
{
istream is(in, in_size);
std::uint32_t index = 0;
std::uint32_t unused = 0;
std::uint8_t kind = 0;
std::uint32_t prefix = 0;
std::uint32_t index;
std::uint32_t unused;
std::uint8_t kind;
std::uint32_t prefix;
read<std::uint32_t>(is, index);
read<std::uint32_t>(is, unused);
read<std::uint8_t>(is, kind);
@@ -208,7 +208,7 @@ nodeobject_compress(void const* in, std::size_t in_size, BufferFactory&& bf)
{
std::size_t n = 0;
std::uint16_t mask = 0;
std::array<std::uint8_t, 512> vh{};
std::array<std::uint8_t, 512> vh;
for (unsigned bit = 0x8000; bit; bit >>= 1)
{
void const* const h = is(32);
@@ -247,7 +247,7 @@ nodeobject_compress(void const* in, std::size_t in_size, BufferFactory&& bf)
}
}
std::array<std::uint8_t, varint_traits<std::size_t>::max> vi{};
std::array<std::uint8_t, varint_traits<std::size_t>::max> vi;
constexpr std::size_t codecType = 1;
auto const vn = write_varint(vi.data(), codecType);
@@ -257,7 +257,7 @@ nodeobject_compress(void const* in, std::size_t in_size, BufferFactory&& bf)
// case 0 was uncompressed data; we always compress now.
case 1: // lz4
{
std::uint8_t* p = nullptr;
std::uint8_t* p;
auto const lzr = NodeStore::lz4_compress(in, in_size, [&p, &vn, &bf](std::size_t n) {
p = reinterpret_cast<std::uint8_t*>(bf(vn + n));
return p + vn;
@@ -287,10 +287,10 @@ filter_inner(void* in, std::size_t in_size)
if (in_size == 525)
{
istream is(in, in_size);
std::uint32_t index = 0;
std::uint32_t unused = 0;
std::uint8_t kind = 0;
std::uint32_t prefix = 0;
std::uint32_t index;
std::uint32_t unused;
std::uint8_t kind;
std::uint32_t prefix;
read<std::uint32_t>(is, index);
read<std::uint32_t>(is, unused);
read<std::uint8_t>(is, kind);

View File

@@ -244,7 +244,15 @@ message TMGetObjectByHash {
message TMLedgerNode {
required bytes nodedata = 1;
optional bytes nodeid = 2; // missing for ledger base data
// Used when protocol version <2.3. Not set for ledger base data.
optional bytes nodeid = 2;
// Used when protocol version >=2.3. Neither value is set for ledger base data.
oneof reference {
bytes id = 3; // Set for inner nodes.
uint32 depth = 4; // Set for leaf nodes.
}
}
enum TMLedgerInfoType {

View File

@@ -26,8 +26,8 @@ class IOUAmount : private boost::totally_ordered<IOUAmount>, private boost::addi
private:
using mantissa_type = std::int64_t;
using exponent_type = int;
mantissa_type mantissa_{};
exponent_type exponent_{};
mantissa_type mantissa_;
exponent_type exponent_;
/** Adjusts the mantissa and exponent to the proper range.

View File

@@ -363,12 +363,11 @@ uint256
getTicketIndex(AccountID const& account, SeqProxy ticketSeq);
template <class... keyletParams>
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
struct keyletDesc
{
std::function<Keylet(keyletParams...)> function;
Json::StaticString expectedLEName;
bool includeInTests{};
bool includeInTests;
};
// This list should include all of the keylet functions that take a single

View File

@@ -56,8 +56,8 @@ struct TAmounts
return *this;
}
In in{};
Out out{};
In in;
Out out;
};
using Amounts = TAmounts<STAmount, STAmount>;

View File

@@ -35,9 +35,9 @@ public:
private:
Asset mAsset;
mantissa_type mValue{};
mantissa_type mValue;
exponent_type mOffset;
bool mIsNegative{};
bool mIsNegative;
public:
using value_type = STAmount;

View File

@@ -86,9 +86,7 @@ inline STLedgerEntry::STLedgerEntry(LedgerEntryType type, uint256 const& key)
{
}
inline STLedgerEntry::STLedgerEntry(
SerialIter&& sit, // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
uint256 const& index)
inline STLedgerEntry::STLedgerEntry(SerialIter&& sit, uint256 const& index)
: STLedgerEntry(sit, index)
{
}

View File

@@ -671,7 +671,7 @@ public:
OptionalProxy&
operator=(std::nullopt_t const&);
OptionalProxy&
operator=(optional_type&& v); // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
operator=(optional_type&& v);
OptionalProxy&
operator=(optional_type const& v);
@@ -766,7 +766,7 @@ STObject::Proxy<T>::assign(U&& u)
st_->makeFieldAbsent(*f_);
return;
}
T* t = nullptr;
T* t;
if (style_ == soeINVALID)
t = dynamic_cast<T*>(st_->getPField(*f_, true));
else
@@ -851,9 +851,7 @@ STObject::OptionalProxy<T>::operator=(std::nullopt_t const&) -> OptionalProxy&
template <class T>
auto
STObject::OptionalProxy<T>::operator=(
optional_type&& v) // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
-> OptionalProxy&
STObject::OptionalProxy<T>::operator=(optional_type&& v) -> OptionalProxy&
{
if (v)
this->assign(std::move(*v));
@@ -932,7 +930,6 @@ STObject::Transform::operator()(detail::STVar const& e) const
//------------------------------------------------------------------------------
// NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved)
inline STObject::STObject(SerialIter&& sit, SField const& name) : STObject(sit, name)
{
}

View File

@@ -179,8 +179,7 @@ sterilize(STTx const& stx);
bool
isPseudoTx(STObject const& tx);
inline STTx::STTx(SerialIter&& sit) // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
: STTx(sit)
inline STTx::STTx(SerialIter&& sit) : STTx(sit)
{
}

View File

@@ -50,7 +50,7 @@ public:
STVar&
operator=(STVar&& rhs);
STVar(STBase&& t) // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
STVar(STBase&& t)
{
p_ = t.move(max_size, &d_);
}

View File

@@ -59,7 +59,7 @@ inplace_bigint_add(std::span<std::uint64_t> a, std::uint64_t b)
return TokenCodecErrc::inputTooSmall;
}
std::uint64_t carry = 0;
std::uint64_t carry;
std::tie(a[0], carry) = carrying_add(a[0], b);
for (auto& v : a.subspan(1))
@@ -162,7 +162,7 @@ b58_10_to_b58_be(std::uint64_t input)
int i = 0;
while (input > 0)
{
std::uint64_t rem = 0;
std::uint64_t rem;
std::tie(input, rem) = div_rem(input, 58);
result[resultSize - 1 - i] = rem;
i += 1;

View File

@@ -112,7 +112,7 @@ getOrThrow(Json::Value const& v, xrpl::SField const& field)
{
auto const s = inner.asString();
// parse as hex
std::uint64_t val = 0;
std::uint64_t val;
auto [p, ec] = std::from_chars(s.data(), s.data() + s.size(), val, 16);

View File

@@ -39,7 +39,7 @@ constexpr std::uint16_t const flagMutable = 0x0010;
inline std::uint16_t
getFlags(uint256 const& id)
{
std::uint16_t flags = 0;
std::uint16_t flags;
memcpy(&flags, id.begin(), 2);
return boost::endian::big_to_native(flags);
}
@@ -47,7 +47,7 @@ getFlags(uint256 const& id)
inline std::uint16_t
getTransferFee(uint256 const& id)
{
std::uint16_t fee = 0;
std::uint16_t fee;
memcpy(&fee, id.begin() + 2, 2);
return boost::endian::big_to_native(fee);
}
@@ -55,7 +55,7 @@ getTransferFee(uint256 const& id)
inline std::uint32_t
getSerial(uint256 const& id)
{
std::uint32_t seq = 0;
std::uint32_t seq;
memcpy(&seq, id.begin() + 28, 4);
return boost::endian::big_to_native(seq);
}
@@ -87,7 +87,7 @@ cipheredTaxon(std::uint32_t tokenSeq, Taxon taxon)
inline Taxon
getTaxon(uint256 const& id)
{
std::uint32_t taxon = 0;
std::uint32_t taxon;
memcpy(&taxon, id.begin() + 24, 4);
taxon = boost::endian::big_to_native(taxon);

View File

@@ -51,19 +51,19 @@ public:
AccountID const& account;
/// Ledger sequence range to search. A value of 0 for min or max
/// means unbounded in that direction (no constraint applied).
LedgerRange ledgerRange{};
std::uint32_t offset = 0;
std::uint32_t limit = 0;
bool bUnlimited{};
LedgerRange ledgerRange;
std::uint32_t offset;
std::uint32_t limit;
bool bUnlimited;
};
struct AccountTxPageOptions
{
AccountID const& account;
LedgerRange ledgerRange{};
LedgerRange ledgerRange;
std::optional<AccountTxMarker> marker;
std::uint32_t limit = 0;
bool bAdmin = false;
std::uint32_t limit;
bool bAdmin;
};
using AccountTx = std::pair<std::shared_ptr<Transaction>, std::shared_ptr<TxMeta>>;
@@ -88,8 +88,8 @@ public:
struct AccountTxResult
{
std::variant<AccountTxs, MetaTxsList> transactions;
LedgerRange ledgerRange{};
uint32_t limit = 0;
LedgerRange ledgerRange;
uint32_t limit;
std::optional<AccountTxMarker> marker;
};

View File

@@ -17,7 +17,7 @@ struct Gossip
{
explicit Item() = default;
int balance{};
int balance;
beast::IP::Endpoint address;
};

View File

@@ -62,7 +62,7 @@ struct Entry : public beast::List<Entry>::Node
std::optional<PublicKey> publicKey;
// Back pointer to the map key (bit of a hack here)
Key const* key{};
Key const* key;
// Number of Consumer references
int refcount;

View File

@@ -13,7 +13,7 @@ struct Import
{
explicit Item() = default;
int balance{};
int balance;
Consumer consumer;
};

View File

@@ -26,6 +26,10 @@ class LoadFeeTrack final
public:
explicit LoadFeeTrack(beast::Journal journal = beast::Journal(beast::Journal::getNullSink()))
: j_(journal)
, localTxnLoadFee_(lftNormalFee)
, remoteTxnLoadFee_(lftNormalFee)
, clusterTxnLoadFee_(lftNormalFee)
, raiseCount_(0)
{
}
@@ -120,10 +124,10 @@ private:
beast::Journal const j_;
std::mutex mutable lock_;
std::uint32_t localTxnLoadFee_{lftNormalFee}; // Scale factor, lftNormalFee = normal fee
std::uint32_t remoteTxnLoadFee_{lftNormalFee}; // Scale factor, lftNormalFee = normal fee
std::uint32_t clusterTxnLoadFee_{lftNormalFee}; // Scale factor, lftNormalFee = normal fee
std::uint32_t raiseCount_{0};
std::uint32_t localTxnLoadFee_; // Scale factor, lftNormalFee = normal fee
std::uint32_t remoteTxnLoadFee_; // Scale factor, lftNormalFee = normal fee
std::uint32_t clusterTxnLoadFee_; // Scale factor, lftNormalFee = normal fee
std::uint32_t raiseCount_;
};
//------------------------------------------------------------------------------

View File

@@ -54,7 +54,7 @@ struct Port
int limit = 0;
// Websocket disconnects if send queue exceeds this limit
std::uint16_t ws_queue_limit{};
std::uint16_t ws_queue_limit;
// Returns `true` if any websocket protocols are specified
bool
@@ -90,7 +90,7 @@ struct ParsedPort
std::string ssl_ciphers;
boost::beast::websocket::permessage_deflate pmd_options;
int limit = 0;
std::uint16_t ws_queue_limit{};
std::uint16_t ws_queue_limit;
std::optional<boost::asio::ip::address> ip;
std::optional<std::uint16_t> port;

View File

@@ -12,7 +12,7 @@ struct SavedState
{
std::string writableDb;
std::string archiveDb;
LedgerIndex lastRotated{};
LedgerIndex lastRotated;
};
/**

View File

@@ -48,14 +48,14 @@ protected:
struct buffer
{
buffer(void const* ptr, std::size_t len) : data(new char[len]), bytes(len)
buffer(void const* ptr, std::size_t len) : data(new char[len]), bytes(len), used(0)
{
memcpy(data.get(), ptr, len);
}
std::unique_ptr<char[]> data;
std::size_t bytes;
std::size_t used{0};
std::size_t used;
};
Port const& port_;

View File

@@ -88,12 +88,8 @@ private:
boost::asio::io_context& ioc_;
acceptor_type acceptor_;
boost::asio::strand<boost::asio::io_context::executor_type> strand_;
bool ssl_{
port_.protocol.count("https") > 0 || port_.protocol.count("wss") > 0 ||
port_.protocol.count("wss2") > 0 || port_.protocol.count("peer") > 0};
bool plain_{
port_.protocol.count("http") > 0 || port_.protocol.count("ws") > 0 ||
port_.protocol.count("ws2")};
bool ssl_;
bool plain_;
static constexpr std::chrono::milliseconds INITIAL_ACCEPT_DELAY{50};
static constexpr std::chrono::milliseconds MAX_ACCEPT_DELAY{2000};
std::chrono::milliseconds accept_delay_{INITIAL_ACCEPT_DELAY};
@@ -278,6 +274,12 @@ Door<Handler>::Door(
, ioc_(io_context)
, acceptor_(io_context)
, strand_(boost::asio::make_strand(io_context))
, ssl_(
port_.protocol.count("https") > 0 || port_.protocol.count("wss") > 0 ||
port_.protocol.count("wss2") > 0 || port_.protocol.count("peer") > 0)
, plain_(
port_.protocol.count("http") > 0 || port_.protocol.count("ws") > 0 ||
port_.protocol.count("ws2"))
, backoff_timer_(io_context)
{
reOpen();
@@ -395,7 +397,7 @@ Door<Handler>::query_fd_stats() const
return std::nullopt;
#else
FDStats s;
struct rlimit rl{};
struct rlimit rl;
if (getrlimit(RLIMIT_NOFILE, &rl) != 0 || rl.rlim_cur == RLIM_INFINITY)
return std::nullopt;
s.limit = static_cast<std::uint64_t>(rl.rlim_cur);

View File

@@ -74,7 +74,7 @@ private:
std::vector<Port> ports_;
std::vector<std::weak_ptr<Door<Handler>>> list_;
int high_ = 0;
std::array<std::size_t, 64> hist_{};
std::array<std::size_t, 64> hist_;
io_list ios_;

View File

@@ -16,6 +16,7 @@
#include <set>
#include <stack>
#include <tuple>
#include <vector>
namespace xrpl {
@@ -253,7 +254,7 @@ public:
bool
getNodeFat(
SHAMapNodeID const& wanted,
std::vector<std::pair<SHAMapNodeID, Blob>>& data,
std::vector<std::tuple<SHAMapNodeID, Blob, bool>>& data,
bool fatLeaves,
std::uint32_t depth) const;
@@ -280,10 +281,45 @@ public:
void
serializeRoot(Serializer& s) const;
/** Add a root node to the SHAMap during synchronization.
*
* This function is used when receiving the root node of a SHAMap from a peer during ledger
* synchronization. The node must already have been deserialized.
*
* @param hash The expected hash of the root node.
* @param rootNode A deserialized root node to add.
* @param filter Optional sync filter to track received nodes.
* @return Status indicating whether the node was useful, duplicate, or invalid.
*
* @note This function expects the rootNode to be a valid, deserialized SHAMapTreeNode. The
* caller is responsible for deserialization and basic validation before calling this
* function.
*/
SHAMapAddNode
addRootNode(SHAMapHash const& hash, Slice const& rootNode, SHAMapSyncFilter* filter);
addRootNode(
SHAMapHash const& hash,
intr_ptr::SharedPtr<SHAMapTreeNode> rootNode,
SHAMapSyncFilter const* filter);
/** Add a known node at a specific position in the SHAMap during synchronization.
*
* This function is used when receiving nodes from peers during ledger synchronization. The node
* is inserted at the position specified by nodeID. The node must already have been
* deserialized.
*
* @param nodeID The position in the tree where this node belongs.
* @param treeNode A deserialized tree node to add.
* @param filter Optional sync filter to track received nodes.
* @return Status indicating whether the node was useful, duplicate, or invalid.
*
* @note This function expects that the caller has already validated that the nodeID is
* consistent with the node's content.
*/
SHAMapAddNode
addKnownNode(SHAMapNodeID const& nodeID, Slice const& rawNode, SHAMapSyncFilter* filter);
addKnownNode(
SHAMapNodeID const& nodeID,
intr_ptr::SharedPtr<SHAMapTreeNode> treeNode,
SHAMapSyncFilter const* filter);
// status functions
void
@@ -344,11 +380,11 @@ private:
intr_ptr::SharedPtr<SHAMapTreeNode>
fetchNodeNT(SHAMapHash const& hash) const;
intr_ptr::SharedPtr<SHAMapTreeNode>
fetchNodeNT(SHAMapHash const& hash, SHAMapSyncFilter* filter) const;
fetchNodeNT(SHAMapHash const& hash, SHAMapSyncFilter const* filter) const;
intr_ptr::SharedPtr<SHAMapTreeNode>
fetchNode(SHAMapHash const& hash) const;
intr_ptr::SharedPtr<SHAMapTreeNode>
checkFilter(SHAMapHash const& hash, SHAMapSyncFilter* filter) const;
checkFilter(SHAMapHash const& hash, SHAMapSyncFilter const* filter) const;
/** Update hashes up to the root */
void
@@ -420,7 +456,7 @@ private:
descendAsync(
SHAMapInnerNode* parent,
int branch,
SHAMapSyncFilter* filter,
SHAMapSyncFilter const* filter,
bool& pending,
descendCallback&&) const;
@@ -429,7 +465,7 @@ private:
SHAMapInnerNode* parent,
SHAMapNodeID const& parentID,
int branch,
SHAMapSyncFilter* filter) const;
SHAMapSyncFilter const* filter) const;
// Non-storing
// Does not hook the returned node to its parent

View File

@@ -116,13 +116,12 @@ protected:
AccountID const account_;
XRPAmount preFeeBalance_{}; // Balance before fees.
virtual ~Transactor() = default;
Transactor(Transactor const&) = delete;
Transactor&
operator=(Transactor const&) = delete;
public:
virtual ~Transactor() = default;
enum ConsequencesFactoryType { Normal, Blocker, Custom };
/** Process the transaction. */
ApplyResult

View File

@@ -15,12 +15,12 @@ class ValidAMM
std::optional<AccountID> ammAccount_;
std::optional<STAmount> lptAMMBalanceAfter_;
std::optional<STAmount> lptAMMBalanceBefore_;
bool ammPoolChanged_{false};
bool ammPoolChanged_;
public:
enum class ZeroAllowed : bool { No = false, Yes = true };
ValidAMM()
ValidAMM() : ammPoolChanged_{false}
{
}
void

View File

@@ -37,7 +37,7 @@ private:
// else the amounts quality
Quality const quality_;
// AMM offer can be consumed once at a given iteration
bool consumed_{false};
bool consumed_;
public:
AMMOffer(

View File

@@ -16,7 +16,7 @@ class BookTip
{
private:
ApplyView& view_;
bool m_valid{false};
bool m_valid;
uint256 m_book;
uint256 m_end;
uint256 m_dir;

View File

@@ -32,10 +32,10 @@ class TOffer : private TOfferBase<TIn, TOut>
{
private:
SLE::pointer m_entry;
Quality m_quality{};
Quality m_quality;
AccountID m_account;
TAmounts<TIn, TOut> m_amounts{};
TAmounts<TIn, TOut> m_amounts;
void
setFieldAmounts();

View File

@@ -19,11 +19,11 @@ public:
{
private:
std::uint32_t const limit_;
std::uint32_t count_{0};
std::uint32_t count_;
beast::Journal j_;
public:
StepCounter(std::uint32_t limit, beast::Journal j) : limit_(limit), j_(j)
StepCounter(std::uint32_t limit, beast::Journal j) : limit_(limit), count_(0), j_(j)
{
}

View File

@@ -12,7 +12,7 @@ struct AmountSpec
{
explicit AmountSpec() = default;
bool native{};
bool native;
union
{
XRPAmount xrp;

View File

@@ -27,7 +27,7 @@ namespace xrpl {
template <class TInAmt, class TOutAmt>
struct StrandResult
{
bool success = false; ///< Strand succeeded
bool success; ///< Strand succeeded
TInAmt in = beast::zero; ///< Currency amount in
TOutAmt out = beast::zero; ///< Currency amount out
std::optional<PaymentSandbox> sandbox; ///< Resulting Sandbox state
@@ -61,7 +61,7 @@ struct StrandResult
}
StrandResult(Strand const& strand, boost::container::flat_set<uint256> ofrsToRm_)
: ofrsToRm(std::move(ofrsToRm_)), ofrsUsed(offersUsed(strand))
: success(false), ofrsToRm(std::move(ofrsToRm_)), ofrsUsed(offersUsed(strand))
{
}
};

View File

@@ -143,7 +143,7 @@ struct LoanProperties
// - A minimum scale required to represent the periodic payment accurately
// All loan state values (principal, interest, fees) are rounded to this
// scale.
std::int32_t loanScale{};
std::int32_t loanScale;
// The principal portion of the first payment.
Number firstPaymentPrincipal;

View File

@@ -10,7 +10,7 @@ struct MPTCreateArgs
{
std::optional<XRPAmount> priorBalance;
AccountID const& account;
std::uint32_t sequence = 0;
std::uint32_t sequence;
std::uint32_t flags = 0;
std::optional<std::uint64_t> maxAmount{};
std::optional<std::uint8_t> assetScale{};

View File

@@ -95,6 +95,11 @@ setCurrentThreadNameImpl(std::string_view name)
{
std::cerr << "WARNING: Thread name \"" << name << "\" (length " << name.size()
<< ") exceeds maximum of " << maxThreadNameLength << " characters on Linux.\n";
XRPL_ASSERT(
false,
"beast::detail::setCurrentThreadNameImpl : Thread name exceeds "
"maximum length for Linux");
}
#endif
}

View File

@@ -151,7 +151,8 @@ PropertyStream::Set::stream() const
//
//------------------------------------------------------------------------------
PropertyStream::Source::Source(std::string const& name) : m_name(name), item_(this)
PropertyStream::Source::Source(std::string const& name)
: m_name(name), item_(this), parent_(nullptr)
{
}

View File

@@ -13,7 +13,9 @@ JobQueue::JobQueue(
Logs& logs,
perf::PerfLog& perfLog)
: m_journal(journal)
, m_lastJob(0)
, m_invalidJobData(JobTypes::instance().getInvalid(), collector, logs)
, m_processCount(0)
, m_workers(*this, &perfLog, "JobQueue", threadCount)
, perfLog_(perfLog)
, m_collector(collector)

View File

@@ -15,14 +15,16 @@ TODO
//------------------------------------------------------------------------------
LoadMonitor::Stats::Stats() : latencyAvg(0), latencyPeak(0)
LoadMonitor::Stats::Stats() : count(0), latencyAvg(0), latencyPeak(0), isOverloaded(false)
{
}
//------------------------------------------------------------------------------
LoadMonitor::LoadMonitor(beast::Journal j)
: mLatencyMSAvg(0)
: mCounts(0)
, mLatencyEvents(0)
, mLatencyMSAvg(0)
, mLatencyMSPeak(0)
, mTargetLatencyAvg(0)
, mTargetLatencyPk(0)

View File

@@ -12,7 +12,9 @@ Workers::Workers(
: m_callback(callback)
, perfLog_(perfLog)
, m_threadNames(threadNames)
, m_allPaused(true)
, m_semaphore(0)
, m_numberOfThreads(0)
, m_activeCount(0)
, m_pauseCount(0)
, m_runningTaskCount(0)
@@ -136,8 +138,11 @@ Workers::deleteWorkers(beast::LockFreeStack<Worker>& stack)
//------------------------------------------------------------------------------
Workers::Worker::Worker(Workers& workers, std::string const& threadName, int const instance)
: m_workers{workers}, threadName_{threadName}, instance_{instance}
: m_workers{workers}
, threadName_{threadName}
, instance_{instance}
, wakeCount_{0}
, shouldExit_{false}
{
thread_ = std::thread{&Workers::Worker::run, this};
}

View File

@@ -252,7 +252,7 @@ FastWriter::writeValue(Value const& value)
// Class StyledWriter
// //////////////////////////////////////////////////////////////////
StyledWriter::StyledWriter()
StyledWriter::StyledWriter() : rightMargin_(74), indentSize_(3)
{
}
@@ -486,7 +486,8 @@ StyledWriter::unindent()
// Class StyledStreamWriter
// //////////////////////////////////////////////////////////////////
StyledStreamWriter::StyledStreamWriter(std::string indentation) : indentation_(indentation)
StyledStreamWriter::StyledStreamWriter(std::string indentation)
: document_(nullptr), rightMargin_(74), indentation_(indentation)
{
}

View File

@@ -1155,87 +1155,57 @@ rippleSendMultiMPT(
beast::Journal j,
WaiveTransferFee waiveFee)
{
// Safe to get MPT since rippleSendMultiMPT is only called by
// accountSendMultiMPT
auto const& issuer = mptIssue.getIssuer();
auto const sle = view.read(keylet::mptIssuance(mptIssue.getMptID()));
if (!sle)
return tecOBJECT_NOT_FOUND;
// For the issuer-as-sender case, track the running total to validate
// against MaximumAmount. The read-only SLE (view.read) is not updated
// by rippleCreditMPT, so a per-iteration SLE read would be stale.
// Use uint64_t, not STAmount, to keep MaximumAmount comparisons in exact
// integer arithmetic. STAmount implicitly converts to Number, whose
// small-scale mantissa (~16 digits) can lose precision for values near
// maxMPTokenAmount (19 digits).
std::uint64_t totalSendAmount{0};
std::uint64_t const maximumAmount = sle->at(~sfMaximumAmount).value_or(maxMPTokenAmount);
std::uint64_t const outstandingAmount = sle->getFieldU64(sfOutstandingAmount);
// actual accumulates the total cost to the sender (includes transfer
// fees for third-party transit sends). takeFromSender accumulates only
// the transit portion that is debited to the issuer in bulk after the
// loop. They diverge when there are transfer fees.
// These may diverge
STAmount takeFromSender{mptIssue};
actual = takeFromSender;
for (auto const& [receiverID, amt] : receivers)
for (auto const& r : receivers)
{
STAmount const amount{mptIssue, amt};
auto const& receiverID = r.first;
STAmount const amount{mptIssue, r.second};
if (amount < beast::zero)
{
return tecINTERNAL; // LCOV_EXCL_LINE
}
if (!amount || senderID == receiverID)
/* If we aren't sending anything or if the sender is the same as the
* receiver then we don't need to do anything.
*/
if (!amount || (senderID == receiverID))
continue;
if (senderID == issuer || receiverID == issuer)
{
// if sender is issuer, check that the new OutstandingAmount will
// not exceed MaximumAmount
if (senderID == issuer)
{
XRPL_ASSERT_PARTS(
takeFromSender == beast::zero,
"xrpl::rippleSendMultiMPT",
"sender == issuer, takeFromSender == zero");
std::uint64_t const sendAmount = amount.mpt().value();
if (view.rules().enabled(fixSecurity3_1_3))
{
// Post-fixSecurity3_1_3: aggregate MaximumAmount
// check. WARNING: the order of conditions is
// critical — each guards the subtraction in the
// next against unsigned underflow. Do not reorder.
bool const exceedsMaximumAmount =
// This send alone exceeds the max cap
sendAmount > maximumAmount ||
// The aggregate of all sends exceeds the max cap
totalSendAmount > maximumAmount - sendAmount ||
// Outstanding + aggregate exceeds the max cap
outstandingAmount > maximumAmount - sendAmount - totalSendAmount;
if (exceedsMaximumAmount)
return tecPATH_DRY;
totalSendAmount += sendAmount;
}
else
{
// Pre-fixSecurity3_1_3: per-iteration MaximumAmount
// check. Reads sfOutstandingAmount from a stale
// view.read() snapshot — incorrect for multi-destination
// sends but retained for ledger replay compatibility.
if (sendAmount > maximumAmount ||
outstandingAmount > maximumAmount - sendAmount)
return tecPATH_DRY;
}
auto const sendAmount = amount.mpt().value();
auto const maximumAmount = sle->at(~sfMaximumAmount).value_or(maxMPTokenAmount);
if (sendAmount > maximumAmount ||
sle->getFieldU64(sfOutstandingAmount) > maximumAmount - sendAmount)
return tecPATH_DRY;
}
// Direct send: redeeming MPTs and/or sending own MPTs.
if (auto const ter = rippleCreditMPT(view, senderID, receiverID, amount, j))
return ter;
actual += amount;
// Do not add amount to takeFromSender, because rippleCreditMPT
// took it.
// Do not add amount to takeFromSender, because rippleCreditMPT took
// it
continue;
}

View File

@@ -4,7 +4,7 @@ namespace xrpl {
namespace NodeStore {
BatchWriter::BatchWriter(Callback& callback, Scheduler& scheduler)
: m_callback(callback), m_scheduler(scheduler)
: m_callback(callback), m_scheduler(scheduler), mWriteLoad(0), mWritePending(false)
{
mWriteSet.reserve(batchWritePreallocationSize);
}

View File

@@ -23,7 +23,7 @@ namespace {
// and follow the format described at http://semver.org/
//------------------------------------------------------------------------------
// clang-format off
char const* const versionString = "3.2.0-b3"
char const* const versionString = "3.2.0-b0"
// clang-format on
;

View File

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

View File

@@ -179,7 +179,7 @@ SHAMap::finishFetch(SHAMapHash const& hash, std::shared_ptr<NodeObject> const& o
// See if a sync filter has a node
intr_ptr::SharedPtr<SHAMapTreeNode>
SHAMap::checkFilter(SHAMapHash const& hash, SHAMapSyncFilter* filter) const
SHAMap::checkFilter(SHAMapHash const& hash, SHAMapSyncFilter const* filter) const
{
if (auto nodeData = filter->getNode(hash))
{
@@ -205,7 +205,7 @@ SHAMap::checkFilter(SHAMapHash const& hash, SHAMapSyncFilter* filter) const
// Get a node without throwing
// Used on maps where missing nodes are expected
intr_ptr::SharedPtr<SHAMapTreeNode>
SHAMap::fetchNodeNT(SHAMapHash const& hash, SHAMapSyncFilter* filter) const
SHAMap::fetchNodeNT(SHAMapHash const& hash, SHAMapSyncFilter const* filter) const
{
auto node = cacheLookup(hash);
if (node)
@@ -318,7 +318,7 @@ SHAMap::descend(
SHAMapInnerNode* parent,
SHAMapNodeID const& parentID,
int branch,
SHAMapSyncFilter* filter) const
SHAMapSyncFilter const* filter) const
{
XRPL_ASSERT(parent->isInner(), "xrpl::SHAMap::descend : valid parent input");
XRPL_ASSERT(
@@ -347,7 +347,7 @@ SHAMapTreeNode*
SHAMap::descendAsync(
SHAMapInnerNode* parent,
int branch,
SHAMapSyncFilter* filter,
SHAMapSyncFilter const* filter,
bool& pending,
descendCallback&& callback) const
{

View File

@@ -122,7 +122,9 @@ selectBranch(SHAMapNodeID const& id, uint256 const& hash)
SHAMapNodeID
SHAMapNodeID::createID(int depth, uint256 const& key)
{
XRPL_ASSERT((depth >= 0) && (depth < 65), "xrpl::SHAMapNodeID::createID : valid branch input");
XRPL_ASSERT(
depth >= 0 && depth <= SHAMap::leafDepth,
"xrpl::SHAMapNodeID::createID : valid branch input");
return SHAMapNodeID(depth, key & depthMask(depth));
}

View File

@@ -392,7 +392,7 @@ SHAMap::getMissingNodes(int max, SHAMapSyncFilter* filter)
bool
SHAMap::getNodeFat(
SHAMapNodeID const& wanted,
std::vector<std::pair<SHAMapNodeID, Blob>>& data,
std::vector<std::tuple<SHAMapNodeID, Blob, bool>>& data,
bool fatLeaves,
std::uint32_t depth) const
{
@@ -438,7 +438,7 @@ SHAMap::getNodeFat(
// Add this node to the reply
s.erase();
node->serializeForWire(s);
data.emplace_back(std::make_pair(nodeID, s.getData()));
data.emplace_back(std::make_tuple(nodeID, s.getData(), node->isLeaf()));
if (node->isInner())
{
@@ -468,7 +468,8 @@ SHAMap::getNodeFat(
// Just include this node
s.erase();
childNode->serializeForWire(s);
data.emplace_back(std::make_pair(childID, s.getData()));
data.emplace_back(
std::make_tuple(childID, s.getData(), childNode->isLeaf()));
}
}
}
@@ -486,8 +487,18 @@ SHAMap::serializeRoot(Serializer& s) const
}
SHAMapAddNode
SHAMap::addRootNode(SHAMapHash const& hash, Slice const& rootNode, SHAMapSyncFilter* filter)
SHAMap::addRootNode(
SHAMapHash const& hash,
intr_ptr::SharedPtr<SHAMapTreeNode> rootNode,
SHAMapSyncFilter const* filter)
{
XRPL_ASSERT(rootNode, "xrpl::SHAMap::addRootNode : non-null root node");
if (!rootNode)
{
JLOG(journal_.error()) << "Null node received";
return SHAMapAddNode::invalid();
}
// we already have a root_ node
if (root_->getHash().isNonZero())
{
@@ -497,14 +508,16 @@ SHAMap::addRootNode(SHAMapHash const& hash, Slice const& rootNode, SHAMapSyncFil
}
XRPL_ASSERT(cowid_ >= 1, "xrpl::SHAMap::addRootNode : valid cowid");
auto node = SHAMapTreeNode::makeFromWire(rootNode);
if (!node || node->getHash() != hash)
if (rootNode->getHash() != hash)
{
JLOG(journal_.warn()) << "Corrupt node received";
return SHAMapAddNode::invalid();
}
if (backed_)
canonicalize(hash, node);
canonicalize(hash, rootNode);
root_ = node;
root_ = std::move(rootNode);
if (root_->isLeaf())
clearSynching();
@@ -521,9 +534,23 @@ SHAMap::addRootNode(SHAMapHash const& hash, Slice const& rootNode, SHAMapSyncFil
}
SHAMapAddNode
SHAMap::addKnownNode(SHAMapNodeID const& node, Slice const& rawNode, SHAMapSyncFilter* filter)
SHAMap::addKnownNode(
SHAMapNodeID const& nodeID,
intr_ptr::SharedPtr<SHAMapTreeNode> treeNode,
SHAMapSyncFilter const* filter)
{
XRPL_ASSERT(!node.isRoot(), "xrpl::SHAMap::addKnownNode : valid node input");
XRPL_ASSERT(!nodeID.isRoot(), "xrpl::SHAMap::addKnownNode : valid node input");
if (nodeID.isRoot())
{
JLOG(journal_.error()) << "Root node received";
return SHAMapAddNode::invalid();
}
XRPL_ASSERT(treeNode, "xrpl::SHAMap::addKnownNode : non-null tree node");
if (!treeNode)
{
JLOG(journal_.error()) << "Null node received";
return SHAMapAddNode::invalid();
}
if (!isSynching())
{
@@ -537,14 +564,14 @@ SHAMap::addKnownNode(SHAMapNodeID const& node, Slice const& rawNode, SHAMapSyncF
while (currNode->isInner() &&
!safe_downcast<SHAMapInnerNode*>(currNode)->isFullBelow(generation) &&
(currNodeID.getDepth() < node.getDepth()))
(currNodeID.getDepth() < nodeID.getDepth()))
{
int const branch = selectBranch(currNodeID, node.getNodeID());
int const branch = selectBranch(currNodeID, nodeID.getNodeID());
XRPL_ASSERT(branch >= 0, "xrpl::SHAMap::addKnownNode : valid branch");
auto inner = safe_downcast<SHAMapInnerNode*>(currNode);
if (inner->isEmptyBranch(branch))
{
JLOG(journal_.warn()) << "Add known node for empty branch" << node;
JLOG(journal_.warn()) << "Add known node for empty branch" << nodeID;
return SHAMapAddNode::invalid();
}
@@ -560,67 +587,44 @@ SHAMap::addKnownNode(SHAMapNodeID const& node, Slice const& rawNode, SHAMapSyncF
if (currNode != nullptr)
continue;
auto newNode = SHAMapTreeNode::makeFromWire(rawNode);
if (!newNode || childHash != newNode->getHash())
if (childHash != treeNode->getHash())
{
JLOG(journal_.warn()) << "Corrupt node received";
return SHAMapAddNode::invalid();
}
// In rare cases, a node can still be corrupt even after hash
// validation. For leaf nodes, we perform an additional check to
// ensure the node's position in the tree is consistent with its
// content to prevent inconsistencies that could
// propagate further down the line.
if (newNode->isLeaf())
{
auto const& actualKey =
safe_downcast<SHAMapLeafNode const*>(newNode.get())->peekItem()->key();
// Validate that this leaf belongs at the target position
auto const expectedNodeID = SHAMapNodeID::createID(node.getDepth(), actualKey);
if (expectedNodeID.getNodeID() != node.getNodeID())
{
JLOG(journal_.debug())
<< "Leaf node position mismatch: "
<< "expected=" << expectedNodeID.getNodeID() << ", actual=" << node.getNodeID();
return SHAMapAddNode::invalid();
}
}
// Inner nodes must be at a level strictly less than 64
// but leaf nodes (while notionally at level 64) can be
// at any depth up to and including 64:
if ((currNodeID.getDepth() > leafDepth) ||
(newNode->isInner() && currNodeID.getDepth() == leafDepth))
(treeNode->isInner() && currNodeID.getDepth() == leafDepth))
{
// Map is provably invalid
state_ = SHAMapState::Invalid;
return SHAMapAddNode::useful();
}
if (currNodeID != node)
if (currNodeID != nodeID)
{
// Either this node is broken or we didn't request it (yet)
JLOG(journal_.warn()) << "unable to hook node " << node;
JLOG(journal_.warn()) << "unable to hook node " << nodeID;
JLOG(journal_.info()) << " stuck at " << currNodeID;
JLOG(journal_.info()) << "got depth=" << node.getDepth()
JLOG(journal_.info()) << "got depth=" << nodeID.getDepth()
<< ", walked to= " << currNodeID.getDepth();
return SHAMapAddNode::useful();
}
if (backed_)
canonicalize(childHash, newNode);
canonicalize(childHash, treeNode);
newNode = prevNode->canonicalizeChild(branch, std::move(newNode));
treeNode = prevNode->canonicalizeChild(branch, std::move(treeNode));
if (filter != nullptr)
{
Serializer s;
newNode->serializeWithPrefix(s);
treeNode->serializeWithPrefix(s);
filter->gotNode(
false, childHash, ledgerSeq_, std::move(s.modData()), newNode->getType());
false, childHash, ledgerSeq_, std::move(s.modData()), treeNode->getType());
}
return SHAMapAddNode::useful();

View File

@@ -10,8 +10,11 @@ AMMOffer<TIn, TOut>::AMMOffer(
TAmounts<TIn, TOut> const& amounts,
TAmounts<TIn, TOut> const& balances,
Quality const& quality)
: ammLiquidity_(ammLiquidity), amounts_(amounts), balances_(balances), quality_(quality)
: ammLiquidity_(ammLiquidity)
, amounts_(amounts)
, balances_(balances)
, quality_(quality)
, consumed_(false)
{
}

View File

@@ -5,7 +5,7 @@
namespace xrpl {
BookTip::BookTip(ApplyView& view, Book const& book)
: view_(view), m_book(getBookBase(book)), m_end(getQualityNext(m_book))
: view_(view), m_valid(false), m_book(getBookBase(book)), m_end(getQualityNext(m_book))
{
}

View File

@@ -0,0 +1,356 @@
#include <test/shamap/common.h>
#include <xrpld/app/ledger/detail/LedgerNodeHelpers.h>
#include <xrpl/beast/unit_test.h>
#include <xrpl/protocol/messages.h>
#include <xrpl/shamap/SHAMap.h>
#include <xrpl/shamap/SHAMapAccountStateLeafNode.h>
#include <xrpl/shamap/SHAMapInnerNode.h>
#include <xrpl/shamap/SHAMapItem.h>
#include <xrpl/shamap/SHAMapTreeNode.h>
#include <bit>
namespace xrpl {
namespace tests {
class LedgerNodeHelpers_test : public beast::unit_test::suite
{
// Helper function to create a simple SHAMapItem for testing.
static boost::intrusive_ptr<SHAMapItem>
makeTestItem(std::uint32_t seed)
{
Serializer s;
s.add32(seed);
s.add32(seed + 1);
s.add32(seed + 2);
return make_shamapitem(s.getSHA512Half(), s.slice());
}
// Helper function to serialize a tree node to wire format.
static std::string
serializeNode(intr_ptr::SharedPtr<SHAMapTreeNode> const& node)
{
Serializer s;
node->serializeForWire(s);
auto const slice = s.slice();
return std::string(std::bit_cast<char const*>(slice.data()), slice.size());
}
void
testValidateLedgerNode()
{
// In the tests below the validity of the content of the node data and ID fields is not
// checked - only that the fields have values when expected. The content of the fields is
// verified in the other tests in this file.
testcase("validateLedgerNode");
// Invalid: missing all fields.
{
protocol::TMLedgerNode const node;
BEAST_EXPECT(!validateLedgerNode(node));
}
// Invalid: missing `nodedata` field.
{
protocol::TMLedgerNode node;
node.set_nodeid("test_nodeid");
BEAST_EXPECT(!validateLedgerNode(node));
}
// Invalid: missing `nodedata` field.
{
protocol::TMLedgerNode node;
node.set_id("test_nodeid");
BEAST_EXPECT(!validateLedgerNode(node));
}
// Invalid: missing `nodedata` field.
{
protocol::TMLedgerNode node;
node.set_depth(1);
BEAST_EXPECT(!validateLedgerNode(node));
}
// Valid: legacy `nodeid` field.
{
protocol::TMLedgerNode node;
node.set_nodedata("test_data");
node.set_nodeid("test_nodeid");
BEAST_EXPECT(validateLedgerNode(node));
}
// Invalid: has both legacy `nodeid` and new `id` fields.
{
protocol::TMLedgerNode node;
node.set_nodedata("test_data");
node.set_nodeid("test_nodeid");
node.set_id("test_nodeid");
BEAST_EXPECT(!validateLedgerNode(node));
}
// Invalid: has both legacy `nodeid` and new `depth` fields.
{
protocol::TMLedgerNode node;
node.set_nodedata("test_data");
node.set_nodeid("test_nodeid");
node.set_depth(5);
BEAST_EXPECT(!validateLedgerNode(node));
}
// Valid: new `id` field.
{
protocol::TMLedgerNode node;
node.set_nodedata("test_data");
node.set_id("test_id");
BEAST_EXPECT(validateLedgerNode(node));
}
// Valid: new `depth` field.
{
protocol::TMLedgerNode node;
node.set_nodedata("test_data");
node.set_depth(5);
BEAST_EXPECT(validateLedgerNode(node));
}
// Valid: `depth` at minimum depth.
{
protocol::TMLedgerNode node;
node.set_nodedata("test_data");
node.set_depth(0);
BEAST_EXPECT(validateLedgerNode(node));
}
// Valid: `depth` at arbitrary depth between minimum and maximum.
{
protocol::TMLedgerNode node;
node.set_nodedata("test_data");
node.set_depth(10);
BEAST_EXPECT(validateLedgerNode(node));
}
// Valid: `depth` at maximum depth.
{
protocol::TMLedgerNode node;
node.set_nodedata("test_data");
node.set_depth(SHAMap::leafDepth);
BEAST_EXPECT(validateLedgerNode(node));
}
// Invalid: `depth` is greater than maximum depth.
{
protocol::TMLedgerNode node;
node.set_nodedata("test_data");
node.set_depth(SHAMap::leafDepth + 1);
BEAST_EXPECT(!validateLedgerNode(node));
}
}
void
testGetTreeNode()
{
testcase("getTreeNode");
// Valid: inner node. It must have at least one child for `serializeNode` to work.
{
auto const innerNode = intr_ptr::make_shared<SHAMapInnerNode>(1);
auto const childNode = intr_ptr::make_shared<SHAMapInnerNode>(1);
innerNode->setChild(0, childNode);
auto const innerData = serializeNode(innerNode);
auto const result = getTreeNode(innerData);
BEAST_EXPECT(result.has_value());
BEAST_EXPECT((*result)->isInner());
}
// Valid: leaf node.
{
auto const leafItem = makeTestItem(12345);
auto const leafNode = intr_ptr::make_shared<SHAMapAccountStateLeafNode>(leafItem, 1);
auto const leafData = serializeNode(leafNode);
auto result = getTreeNode(leafData);
BEAST_EXPECT(result.has_value());
BEAST_EXPECT((*result)->isLeaf());
}
// Invalid: empty data.
{
auto const result = getTreeNode("");
BEAST_EXPECT(!result.has_value());
}
// Invalid: garbage data.
{
auto const result = getTreeNode("invalid");
BEAST_EXPECT(!result.has_value());
}
// Invalid: truncated data.
{
auto const leafItem = makeTestItem(54321);
auto const leafNode = intr_ptr::make_shared<SHAMapAccountStateLeafNode>(leafItem, 1);
// Truncate the data to trigger an exception in SHAMapTreeNode::makeAccountState when
// the data is used to deserialize the node.
uint256 const tag;
auto const leafData = serializeNode(leafNode).substr(0, tag.bytes - 1);
auto const result = getTreeNode(leafData);
BEAST_EXPECT(!result.has_value());
}
}
void
testGetSHAMapNodeID()
{
testcase("getSHAMapNodeID");
{
// Tests using inner nodes at various depths.
auto const innerNode = intr_ptr::make_shared<SHAMapInnerNode>(1);
auto const childNode = intr_ptr::make_shared<SHAMapInnerNode>(1);
innerNode->setChild(0, childNode);
auto const innerData = serializeNode(innerNode);
// Valid: legacy `nodeid` field at arbitrary depth.
{
auto const innerDepth = 3;
auto const innerID = SHAMapNodeID::createID(innerDepth, uint256{});
protocol::TMLedgerNode node;
node.set_nodedata(innerData);
node.set_nodeid(innerID.getRawString());
auto const result = getSHAMapNodeID(node, innerNode);
BEAST_EXPECT(result.has_value());
BEAST_EXPECT(*result == innerID);
}
// Valid: new `id` field at minimum depth.
{
auto const innerDepth = 0;
auto const innerID = SHAMapNodeID::createID(innerDepth, uint256{});
protocol::TMLedgerNode node;
node.set_nodedata(innerData);
node.set_id(innerID.getRawString());
auto const result = getSHAMapNodeID(node, innerNode);
BEAST_EXPECT(result.has_value());
BEAST_EXPECT(*result == innerID);
}
// Invalid: new `depth` field should not be used for inner nodes.
{
protocol::TMLedgerNode node;
node.set_nodedata(innerData);
node.set_depth(10);
auto const result = getSHAMapNodeID(node, innerNode);
BEAST_EXPECT(!result.has_value());
}
}
{
// Tests using leaf nodes at various depths.
auto const leafItem = makeTestItem(12345);
auto const leafNode = intr_ptr::make_shared<SHAMapAccountStateLeafNode>(leafItem, 1);
auto const leafData = serializeNode(leafNode);
auto const leafKey = leafItem->key();
// Valid: legacy `nodeid` field at arbitrary depth.
{
auto const leafDepth = 5;
auto const leafID = SHAMapNodeID::createID(leafDepth, leafKey);
protocol::TMLedgerNode ledgerNode;
ledgerNode.set_nodedata(leafData);
ledgerNode.set_nodeid(leafID.getRawString());
auto result = getSHAMapNodeID(ledgerNode, leafNode);
BEAST_EXPECT(result.has_value());
BEAST_EXPECT(*result == leafID);
}
// Invalid: new `id` field should not be used for leaf nodes.
{
auto const leafDepth = 5;
auto const leafID = SHAMapNodeID::createID(leafDepth, leafKey);
protocol::TMLedgerNode ledgerNode;
ledgerNode.set_nodedata(leafData);
ledgerNode.set_id(leafID.getRawString());
auto result = getSHAMapNodeID(ledgerNode, leafNode);
BEAST_EXPECT(!result.has_value());
}
// Valid: new `depth` field at minimum depth.
{
auto const leafDepth = 0;
auto const leafID = SHAMapNodeID::createID(leafDepth, leafKey);
protocol::TMLedgerNode node;
node.set_nodedata(leafData);
node.set_depth(leafDepth);
auto result = getSHAMapNodeID(node, leafNode);
BEAST_EXPECT(result.has_value());
BEAST_EXPECT(*result == leafID);
}
// Valid: new `depth` field at arbitrary depth between minimum and maximum.
{
auto const leafDepth = 10;
auto const leafID = SHAMapNodeID::createID(leafDepth, leafKey);
protocol::TMLedgerNode ledgerNode;
ledgerNode.set_nodedata(leafData);
ledgerNode.set_depth(leafDepth);
auto result = getSHAMapNodeID(ledgerNode, leafNode);
BEAST_EXPECT(result.has_value());
BEAST_EXPECT(*result == leafID);
}
// Valid: new `depth` field at maximum depth.
// Note that we do not test a depth greater than the maximum depth, because the proto
// message is assumed to have been validated by the time the getSHAMapNodeID function is
// called.
{
auto const leafDepth = SHAMap::leafDepth;
auto const leafID = SHAMapNodeID::createID(leafDepth, leafKey);
protocol::TMLedgerNode node;
node.set_nodedata(leafData);
node.set_depth(leafDepth);
auto result = getSHAMapNodeID(node, leafNode);
BEAST_EXPECT(result.has_value());
BEAST_EXPECT(*result == leafID);
}
// Invalid: legacy `nodeid` field where the node ID is inconsistent with the key.
{
auto const otherItem = makeTestItem(54321);
auto const otherNode =
intr_ptr::make_shared<SHAMapAccountStateLeafNode>(otherItem, 1);
auto const otherData = serializeNode(otherNode);
auto const otherKey = otherItem->key();
auto const otherDepth = 1;
auto const otherID = SHAMapNodeID::createID(otherDepth, otherKey);
protocol::TMLedgerNode ledgerNode;
ledgerNode.set_nodedata(otherData);
ledgerNode.set_nodeid(otherID.getRawString());
auto result = getSHAMapNodeID(ledgerNode, leafNode);
BEAST_EXPECT(!result.has_value());
}
}
}
public:
void
run() override
{
testValidateLedgerNode();
testGetTreeNode();
testGetSHAMapNodeID();
}
};
BEAST_DEFINE_TESTSUITE(LedgerNodeHelpers, app, xrpl);
} // namespace tests
} // namespace xrpl

View File

@@ -6,7 +6,6 @@
#include <xrpl/basics/base_uint.h>
#include <xrpl/beast/utility/Zero.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/TxFlags.h>
@@ -3273,123 +3272,6 @@ class MPToken_test : public beast::unit_test::suite
mptAlice.claw(alice, bob, 1, tecNO_PERMISSION);
}
void
testMultiSendMaximumAmount(FeatureBitset features)
{
// Verify that rippleSendMultiMPT correctly enforces MaximumAmount
// when the issuer sends to multiple receivers. Pre-fixSecurity3_1_3,
// a stale view.read() snapshot caused per-iteration checks to miss
// aggregate overflows. Post-fix, a running total is used instead.
testcase("Multi-send MaximumAmount enforcement");
using namespace test::jtx;
Account const issuer("issuer");
Account const alice("alice");
Account const bob("bob");
std::uint64_t constexpr maxAmt = 150;
Env env{*this, features};
MPTTester mptt(env, issuer, {.holders = {alice, bob}});
mptt.create({.maxAmt = maxAmt, .ownerCount = 1, .flags = tfMPTCanTransfer});
mptt.authorize({.account = alice});
mptt.authorize({.account = bob});
Asset const asset{MPTIssue{mptt.issuanceID()}};
// Each test case creates a fresh ApplyView and calls
// accountSendMulti from the issuer to the given receivers.
auto const runTest = [&](MultiplePaymentDestinations const& receivers,
TER expectedTer,
std::optional<std::uint64_t> expectedOutstanding,
std::string const& label) {
ApplyViewImpl av(&*env.current(), tapNONE);
auto const ter =
accountSendMulti(av, issuer.id(), asset, receivers, env.app().getJournal("View"));
BEAST_EXPECTS(ter == expectedTer, label);
// Only verify OutstandingAmount on success — on error the
// view may contain partial state and must be discarded.
if (expectedOutstanding)
{
auto const sle = av.peek(keylet::mptIssuance(mptt.issuanceID()));
if (!BEAST_EXPECT(sle))
return;
BEAST_EXPECTS(sle->getFieldU64(sfOutstandingAmount) == *expectedOutstanding, label);
}
};
using R = MultiplePaymentDestinations;
// Post-amendment: aggregate check with running total
runTest(
R{{alice.id(), 100}, {bob.id(), 100}},
tecPATH_DRY,
std::nullopt,
"aggregate exceeds max");
runTest(R{{alice.id(), 75}, {bob.id(), 75}}, tesSUCCESS, maxAmt, "aggregate at boundary");
runTest(R{{alice.id(), 50}, {bob.id(), 50}}, tesSUCCESS, 100, "aggregate within limit");
runTest(
R{{alice.id(), 150}, {bob.id(), 0}},
tesSUCCESS,
maxAmt,
"one receiver at max, other zero");
runTest(
R{{alice.id(), 151}, {bob.id(), 0}},
tecPATH_DRY,
std::nullopt,
"one receiver exceeds max, other zero");
// Issue 50 tokens so outstandingAmount is nonzero, then verify
// the third condition: outstandingAmount > maximumAmount - sendAmount - totalSendAmount
mptt.pay(issuer, alice, 50);
env.close();
// maxAmt=150, outstanding=50, so 100 more available
runTest(
R{{alice.id(), 50}, {bob.id(), 50}},
tesSUCCESS,
maxAmt,
"nonzero outstanding, aggregate at boundary");
runTest(
R{{alice.id(), 50}, {bob.id(), 51}},
tecPATH_DRY,
std::nullopt,
"nonzero outstanding, aggregate exceeds max");
runTest(
R{{alice.id(), 100}, {bob.id(), 0}},
tesSUCCESS,
maxAmt,
"nonzero outstanding, single send at remaining capacity");
runTest(
R{{alice.id(), 101}, {bob.id(), 0}},
tecPATH_DRY,
std::nullopt,
"nonzero outstanding, single send exceeds remaining capacity");
// Pre-amendment: the stale per-iteration check allows each
// individual send (100 <= 150) even though the aggregate (200)
// exceeds MaximumAmount. Preserved for ledger replay.
{
// KNOWN BUG (pre-fixSecurity3_1_3): preserved for ledger replay only
env.disableFeature(fixSecurity3_1_3);
runTest(
R{{alice.id(), 100}, {bob.id(), 100}},
tesSUCCESS,
250,
"pre-amendment allows over-send");
env.enableFeature(fixSecurity3_1_3);
}
}
public:
void
run() override
@@ -3397,7 +3279,6 @@ public:
using namespace test::jtx;
FeatureBitset const all{testable_amendments()};
testMultiSendMaximumAmount(all);
// MPTokenIssuanceCreate
testCreateValidation(all - featureSingleAssetVault);
testCreateValidation(all - featurePermissionedDomains);

View File

@@ -231,7 +231,7 @@ struct Peer
// Number of proposers in the prior round
std::size_t prevProposers = 0;
// Duration of prior round
std::chrono::milliseconds prevRoundTime{};
std::chrono::milliseconds prevRoundTime;
// Quorum of validations needed for a ledger to be fully validated
// TODO: Use the logic in ValidatorList to set this dynamically
@@ -501,10 +501,16 @@ struct Peer
NetClock::duration const& closeResolution,
ConsensusCloseTimes const& rawCloseTimes,
ConsensusMode const& mode,
Json::Value const& consensusJson)
Json::Value&& consensusJson)
{
onAccept(
result, prevLedger, closeResolution, rawCloseTimes, mode, consensusJson, validating());
result,
prevLedger,
closeResolution,
rawCloseTimes,
mode,
std::move(consensusJson),
validating());
}
void
@@ -514,10 +520,10 @@ struct Peer
NetClock::duration const& closeResolution,
ConsensusCloseTimes const& rawCloseTimes,
ConsensusMode const& mode,
Json::Value const& consensusJson,
Json::Value&& consensusJson,
bool const validating)
{
schedule(delays.ledgerAccept, [mode, result, prevLedger, closeResolution, this]() {
schedule(delays.ledgerAccept, [=, this]() {
bool const proposing = mode == ConsensusMode::proposing;
bool const consensusFail = result.state == ConsensusState::MovedOn;

View File

@@ -100,8 +100,7 @@ public:
{
}
TxSet(MutableTxSet&& m) // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
: txs_{m.txs_}, id_{calcID(txs_)}
TxSet(MutableTxSet&& m) : txs_{std::move(m.txs_)}, id_{calcID(txs_)}
{
}
@@ -162,7 +161,7 @@ private:
TxSetType txs_;
//! The unique ID of this tx set
ID id_{};
ID id_;
};
//------------------------------------------------------------------------------

View File

@@ -24,7 +24,7 @@ private:
operator=(SignSubmitRunner&&) = delete;
SignSubmitRunner(Env& env, JTx&& jt, std::source_location loc)
: env_(env), jt_(std::move(jt)), loc_(loc)
: env_(env), jt_(jt), loc_(loc)
{
}

View File

@@ -99,7 +99,7 @@ private:
static inline std::uint32_t fee = 0;
Env& env_;
AccountID owner_;
std::uint32_t documentID_{};
std::uint32_t documentID_;
private:
void

View File

@@ -12,7 +12,7 @@ namespace detail {
class flags_helper
{
protected:
std::uint32_t mask_{0};
std::uint32_t mask_;
private:
void
@@ -79,7 +79,7 @@ private:
protected:
template <class... Args>
flags_helper(Args... args)
flags_helper(Args... args) : mask_(0)
{
set_args(args...);
}

View File

@@ -12,7 +12,7 @@ namespace test {
namespace jtx {
namespace oracle {
Oracle::Oracle(Env& env, CreateArg const& arg, bool submit) : env_(env)
Oracle::Oracle(Env& env, CreateArg const& arg, bool submit) : env_(env), documentID_{}
{
// LastUpdateTime is checked to be in range
// {close-maxLastUpdateTimeDelta, close+maxLastUpdateTimeDelta}.

View File

@@ -8,14 +8,12 @@ namespace test {
namespace jtx {
qualityInPercent::qualityInPercent(double percent)
// NOLINTNEXTLINE(cppcoreguidelines-use-default-member-init)
: qIn_(static_cast<std::uint32_t>((percent / 100) * QUALITY_ONE))
{
assert(percent <= 400 && percent >= 0);
}
qualityOutPercent::qualityOutPercent(double percent)
// NOLINTNEXTLINE(cppcoreguidelines-use-default-member-init)
: qOut_(static_cast<std::uint32_t>((percent / 100) * QUALITY_ONE))
{
assert(percent <= 400 && percent >= 0);

View File

@@ -413,6 +413,7 @@ XChainBridgeObjects::XChainBridgeObjects()
}
return r;
}())
, quorum(UT_XCHAIN_DEFAULT_QUORUM)
, reward(XRP(1))
, split_reward_quorum(divide(reward, STAmount(UT_XCHAIN_DEFAULT_QUORUM), reward.issue()))
, split_reward_everyone(divide(reward, STAmount(UT_XCHAIN_DEFAULT_NUM_SIGNERS), reward.issue()))

View File

@@ -25,7 +25,7 @@ public:
class qualityInPercent
{
private:
std::uint32_t qIn_; // NOLINT(cppcoreguidelines-use-default-member-init)
std::uint32_t qIn_;
public:
explicit qualityInPercent(double percent);
@@ -53,7 +53,7 @@ public:
class qualityOutPercent
{
private:
std::uint32_t qOut_; // NOLINT(cppcoreguidelines-use-default-member-init)
std::uint32_t qOut_;
public:
explicit qualityOutPercent(double percent);

View File

@@ -170,7 +170,7 @@ struct XChainBridgeObjects
std::vector<signer> const alt_signers;
std::vector<Account> const payee;
std::vector<Account> const payees;
std::uint32_t const quorum{UT_XCHAIN_DEFAULT_QUORUM};
std::uint32_t const quorum;
STAmount const reward; // 1 xrp
STAmount const split_reward_quorum; // 250,000 drops

View File

@@ -60,8 +60,8 @@ public:
negotiateProtocolVersion("RTXP/1.2, XRPL/2.0, XRPL/2.1") == make_protocol(2, 1));
BEAST_EXPECT(negotiateProtocolVersion("XRPL/2.2") == make_protocol(2, 2));
BEAST_EXPECT(
negotiateProtocolVersion("RTXP/1.2, XRPL/2.2, XRPL/2.3, XRPL/999.999") ==
make_protocol(2, 2));
negotiateProtocolVersion("RTXP/1.2, XRPL/2.3, XRPL/2.4, XRPL/999.999") ==
make_protocol(2, 3));
BEAST_EXPECT(negotiateProtocolVersion("XRPL/999.999, WebSocket/1.0") == std::nullopt);
BEAST_EXPECT(negotiateProtocolVersion("") == std::nullopt);
}

View File

@@ -99,14 +99,17 @@ public:
destination.setSynching();
{
std::vector<std::pair<SHAMapNodeID, Blob>> a;
std::vector<std::tuple<SHAMapNodeID, Blob, bool>> a;
BEAST_EXPECT(source.getNodeFat(SHAMapNodeID(), a, rand_bool(eng_), rand_int(eng_, 2)));
unexpected(a.empty(), "NodeSize");
BEAST_EXPECT(destination.addRootNode(source.getHash(), makeSlice(a[0].second), nullptr)
.isGood());
auto node = SHAMapTreeNode::makeFromWire(makeSlice(std::get<1>(a[0])));
if (!node)
fail("", __FILE__, __LINE__);
BEAST_EXPECT(
destination.addRootNode(source.getHash(), std::move(node), nullptr).isGood());
}
do
@@ -120,7 +123,7 @@ public:
break;
// get as many nodes as possible based on this information
std::vector<std::pair<SHAMapNodeID, Blob>> b;
std::vector<std::tuple<SHAMapNodeID, Blob, bool>> b;
for (auto& it : nodesMissing)
{
@@ -142,7 +145,10 @@ public:
// Don't use BEAST_EXPECT here b/c it will be called a
// non-deterministic number of times and the number of tests run
// should be deterministic
if (!destination.addKnownNode(b[i].first, makeSlice(b[i].second), nullptr)
auto node = SHAMapTreeNode::makeFromWire(makeSlice(std::get<1>(b[i])));
if (!node)
fail("", __FILE__, __LINE__);
if (!destination.addKnownNode(std::get<0>(b[i]), std::move(node), nullptr)
.isUseful())
fail("", __FILE__, __LINE__);
}

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