From ff02269c0dd1707b38ae783fdf9ba05b07037af7 Mon Sep 17 00:00:00 2001 From: Bart Date: Mon, 22 Jun 2026 18:35:28 -0400 Subject: [PATCH 01/14] refactor: Use dispatch instead of post (#7438) Co-authored-by: Bart <11445373+bthomee@users.noreply.github.com> --- src/xrpld/overlay/detail/PeerImp.cpp | 367 ++++++++++++--------------- 1 file changed, 167 insertions(+), 200 deletions(-) diff --git a/src/xrpld/overlay/detail/PeerImp.cpp b/src/xrpld/overlay/detail/PeerImp.cpp index 21e84d6fc7..e1d7d23215 100644 --- a/src/xrpld/overlay/detail/PeerImp.cpp +++ b/src/xrpld/overlay/detail/PeerImp.cpp @@ -70,7 +70,6 @@ #include #include #include -#include #include #include #include @@ -198,78 +197,70 @@ stringIsUInt256Sized(std::string const& pBuffStr) void PeerImp::run() { - if (!strand_.running_in_this_thread()) - { - post(strand_, std::bind(&PeerImp::run, shared_from_this())); - return; - } + dispatch(strand_, [self = shared_from_this()]() { + auto parseLedgerHash = [](std::string_view value) -> std::optional { + if (uint256 ret; ret.parseHex(value)) + return ret; - auto parseLedgerHash = [](std::string_view value) -> std::optional { - if (uint256 ret; ret.parseHex(value)) - return ret; + if (auto const s = base64Decode(value); s.size() == uint256::size()) + return uint256::fromRaw(s); - if (auto const s = base64Decode(value); s.size() == uint256::size()) - return uint256::fromRaw(s); + return std::nullopt; + }; - return std::nullopt; - }; + std::optional closed; + std::optional previous; - std::optional closed; - std::optional previous; + if (auto const iter = self->headers_.find("Closed-Ledger"); iter != self->headers_.end()) + { + closed = parseLedgerHash(iter->value()); - if (auto const iter = headers_.find("Closed-Ledger"); iter != headers_.end()) - { - closed = parseLedgerHash(iter->value()); + if (!closed) + self->fail("Malformed handshake data (1)"); + } - if (!closed) - fail("Malformed handshake data (1)"); - } + if (auto const iter = self->headers_.find("Previous-Ledger"); iter != self->headers_.end()) + { + previous = parseLedgerHash(iter->value()); - if (auto const iter = headers_.find("Previous-Ledger"); iter != headers_.end()) - { - previous = parseLedgerHash(iter->value()); + if (!previous) + self->fail("Malformed handshake data (2)"); + } - if (!previous) - fail("Malformed handshake data (2)"); - } + if (previous && !closed) + self->fail("Malformed handshake data (3)"); - if (previous && !closed) - fail("Malformed handshake data (3)"); + { + std::scoped_lock const sl(self->recentLock_); + if (closed) + self->closedLedgerHash_ = *closed; + if (previous) + self->previousLedgerHash_ = *previous; + } - { - std::scoped_lock const sl(recentLock_); - if (closed) - closedLedgerHash_ = *closed; - if (previous) - previousLedgerHash_ = *previous; - } + if (self->inbound_) + { + self->doAccept(); + } + else + { + self->doProtocolStart(); + } - if (inbound_) - { - doAccept(); - } - else - { - doProtocolStart(); - } - - // Anything else that needs to be done with the connection should be - // done in doProtocolStart + // Anything else that needs to be done with the connection should be + // done in doProtocolStart + }); } void PeerImp::stop() { - if (!strand_.running_in_this_thread()) - { - post(strand_, std::bind(&PeerImp::stop, shared_from_this())); - return; - } + dispatch(strand_, [self = shared_from_this()]() { + if (!self->socket_.is_open()) + return; - if (!socket_.is_open()) - return; - - close(); + self->close(); + }); } //------------------------------------------------------------------------------ @@ -277,126 +268,111 @@ PeerImp::stop() void PeerImp::send(std::shared_ptr const& m) { - if (!strand_.running_in_this_thread()) - { - post(strand_, std::bind(&PeerImp::send, shared_from_this(), m)); - return; - } - if (gracefulClose_) - return; - if (detaching_) - return; - if (!socket_.is_open()) - return; + dispatch(strand_, [self = shared_from_this(), m]() { + if (self->gracefulClose_) + return; + if (self->detaching_) + return; + if (!self->socket_.is_open()) + return; - auto validator = m->getValidatorKey(); - if (validator && !squelch_.expireSquelch(*validator)) - { - overlay_.reportOutboundTraffic( - TrafficCount::Category::SquelchSuppressed, - static_cast(m->getBuffer(compressionEnabled_).size())); - return; - } + auto validator = m->getValidatorKey(); + if (validator && !self->squelch_.expireSquelch(*validator)) + { + self->overlay_.reportOutboundTraffic( + TrafficCount::Category::SquelchSuppressed, + static_cast(m->getBuffer(self->compressionEnabled_).size())); + return; + } - // report categorized outgoing traffic - overlay_.reportOutboundTraffic( - safeCast(m->getCategory()), - static_cast(m->getBuffer(compressionEnabled_).size())); + // report categorized outgoing traffic + self->overlay_.reportOutboundTraffic( + safeCast(m->getCategory()), + static_cast(m->getBuffer(self->compressionEnabled_).size())); - // report total outgoing traffic - overlay_.reportOutboundTraffic( - TrafficCount::Category::Total, static_cast(m->getBuffer(compressionEnabled_).size())); + // report total outgoing traffic + self->overlay_.reportOutboundTraffic( + TrafficCount::Category::Total, + static_cast(m->getBuffer(self->compressionEnabled_).size())); - auto sendqSize = sendQueue_.size(); + auto sendqSize = self->sendQueue_.size(); - if (sendqSize < Tuning::kTargetSendQueue) - { - // To detect a peer that does not read from their - // side of the connection, we expect a peer to have - // a small senq periodically - largeSendq_ = 0; - } - else if (auto sink = journal_.debug(); sink && (sendqSize % Tuning::kSendQueueLogFreq) == 0) - { - std::string const n = name(); - sink << n << " sendq: " << sendqSize; - } + if (sendqSize < Tuning::kTargetSendQueue) + { + // To detect a peer that does not read from their + // side of the connection, we expect a peer to have + // a small sendq periodically + self->largeSendq_ = 0; + } + else if ( + auto sink = self->journal_.debug(); + sink && (sendqSize % Tuning::kSendQueueLogFreq) == 0) + { + std::string const n = self->name(); + sink << n << " sendq: " << sendqSize; + } - sendQueue_.push(m); + self->sendQueue_.push(m); - if (sendqSize != 0) - return; + if (sendqSize != 0) + return; - boost::asio::async_write( - stream_, - boost::asio::buffer(sendQueue_.front()->getBuffer(compressionEnabled_)), - bind_executor( - strand_, - std::bind( - &PeerImp::onWriteMessage, - shared_from_this(), - std::placeholders::_1, - std::placeholders::_2))); + boost::asio::async_write( + self->stream_, + boost::asio::buffer(self->sendQueue_.front()->getBuffer(self->compressionEnabled_)), + bind_executor( + self->strand_, + std::bind( + &PeerImp::onWriteMessage, self, std::placeholders::_1, std::placeholders::_2))); + }); } void PeerImp::sendTxQueue() { - if (!strand_.running_in_this_thread()) - { - post(strand_, std::bind(&PeerImp::sendTxQueue, shared_from_this())); - return; - } - - if (!txQueue_.empty()) - { - protocol::TMHaveTransactions ht; - std::ranges::for_each( - txQueue_, [&](auto const& hash) { ht.add_hashes(hash.data(), hash.size()); }); - JLOG(pJournal_.trace()) << "sendTxQueue " << txQueue_.size(); - txQueue_.clear(); - send(std::make_shared(ht, protocol::mtHAVE_TRANSACTIONS)); - } + dispatch(strand_, [self = shared_from_this()]() { + if (!self->txQueue_.empty()) + { + protocol::TMHaveTransactions ht; + std::ranges::for_each( + self->txQueue_, [&](auto const& hash) { ht.add_hashes(hash.data(), hash.size()); }); + JLOG(self->pJournal_.trace()) << "sendTxQueue " << self->txQueue_.size(); + self->txQueue_.clear(); + self->send(std::make_shared(ht, protocol::mtHAVE_TRANSACTIONS)); + } + }); } void PeerImp::addTxQueue(uint256 const& hash) { - if (!strand_.running_in_this_thread()) - { - post(strand_, std::bind(&PeerImp::addTxQueue, shared_from_this(), hash)); - return; - } + dispatch(strand_, [self = shared_from_this(), hash]() { + if (self->txQueue_.size() == reduce_relay::kMaxTxQueueSize) + { + JLOG(self->pJournal_.warn()) << "addTxQueue exceeds the cap"; + self->sendTxQueue(); + } - if (txQueue_.size() == reduce_relay::kMaxTxQueueSize) - { - JLOG(pJournal_.warn()) << "addTxQueue exceeds the cap"; - sendTxQueue(); - } - - txQueue_.insert(hash); - JLOG(pJournal_.trace()) << "addTxQueue " << txQueue_.size(); + self->txQueue_.insert(hash); + JLOG(self->pJournal_.trace()) << "addTxQueue " << self->txQueue_.size(); + }); } void PeerImp::removeTxQueue(uint256 const& hash) { - if (!strand_.running_in_this_thread()) - { - post(strand_, std::bind(&PeerImp::removeTxQueue, shared_from_this(), hash)); - return; - } - - auto removed = txQueue_.erase(hash); - JLOG(pJournal_.trace()) << "removeTxQueue " << removed; + dispatch(strand_, [self = shared_from_this(), hash]() { + auto removed = self->txQueue_.erase(hash); + JLOG(self->pJournal_.trace()) << "removeTxQueue " << removed; + }); } void PeerImp::charge(Resource::Charge const& fee, std::string const& context) { - dispatch(strand_, [this, self = shared_from_this(), fee, context]() { - if ((usage_.charge(fee, context) == Resource::Disposition::Drop) && - usage_.disconnect(pJournal_)) + dispatch(strand_, [self = shared_from_this(), fee, context]() { + if ((self->usage_.charge(fee, context) == Resource::Disposition::Drop) && + self->usage_.disconnect(self->pJournal_)) { // Idempotent: only the first worker to observe Drop counts the // metric and posts fail(). Without the guard, several queued @@ -405,11 +381,11 @@ PeerImp::charge(Resource::Charge const& fee, std::string const& context) // shutdowns. fail(std::string const&) self-posts to strand_ // when invoked off-strand. bool expected = false; - if (chargeDisconnectFired_.compare_exchange_strong( + if (self->chargeDisconnectFired_.compare_exchange_strong( expected, true, std::memory_order_acq_rel)) { - overlay_.incPeerDisconnectCharges(); - fail("charge: Resources"); + self->overlay_.incPeerDisconnectCharges(); + self->fail("charge: Resources"); } } }); @@ -640,20 +616,14 @@ PeerImp::close() void PeerImp::fail(std::string const& reason) { - if (!strand_.running_in_this_thread()) - { - post( - strand_, - std::bind( - (void (Peer::*)(std::string const&))&PeerImp::fail, shared_from_this(), reason)); - return; - } - if (journal_.active(beast::Severity::Warning) && socket_.is_open()) - { - std::string const n = name(); - JLOG(journal_.warn()) << n << " failed: " << reason; - } - close(); + dispatch(strand_, [self = shared_from_this(), reason]() { + if (self->journal_.active(beast::Severity::Warning) && self->socket_.is_open()) + { + std::string const n = self->name(); + JLOG(self->journal_.warn()) << n << " failed: " << reason; + } + self->close(); + }); } void @@ -2752,45 +2722,42 @@ PeerImp::onMessage(std::shared_ptr const& m) void PeerImp::onMessage(std::shared_ptr const& m) { - using on_message_fn = void (PeerImp::*)(std::shared_ptr const&); - if (!strand_.running_in_this_thread()) - { - post(strand_, std::bind((on_message_fn)&PeerImp::onMessage, shared_from_this(), m)); - return; - } + dispatch(strand_, [self = shared_from_this(), m]() { + if (!m->has_validatorpubkey()) + { + self->fee_.update(Resource::kFeeInvalidData, "squelch no pubkey"); + return; + } + auto validator = m->validatorpubkey(); + auto const slice{makeSlice(validator)}; + if (!publicKeyType(slice)) + { + self->fee_.update(Resource::kFeeInvalidData, "squelch bad pubkey"); + return; + } + PublicKey const key(slice); - if (!m->has_validatorpubkey()) - { - fee_.update(Resource::kFeeInvalidData, "squelch no pubkey"); - return; - } - auto validator = m->validatorpubkey(); - auto const slice{makeSlice(validator)}; - if (!publicKeyType(slice)) - { - fee_.update(Resource::kFeeInvalidData, "squelch bad pubkey"); - return; - } - PublicKey const key(slice); + // Ignore the squelch for validator's own messages. + if (key == self->app_.getValidationPublicKey()) + { + JLOG(self->pJournal_.debug()) + << "onMessage: TMSquelch discarding validator's squelch " << slice; + return; + } - // Ignore the squelch for validator's own messages. - if (key == app_.getValidationPublicKey()) - { - JLOG(pJournal_.debug()) << "onMessage: TMSquelch discarding validator's squelch " << slice; - return; - } + std::uint32_t const duration = m->has_squelchduration() ? m->squelchduration() : 0; + if (!m->squelch()) + { + self->squelch_.removeSquelch(key); + } + else if (!self->squelch_.addSquelch(key, std::chrono::seconds{duration})) + { + self->fee_.update(Resource::kFeeInvalidData, "squelch duration"); + } - std::uint32_t const duration = m->has_squelchduration() ? m->squelchduration() : 0; - if (!m->squelch()) - { - squelch_.removeSquelch(key); - } - else if (!squelch_.addSquelch(key, std::chrono::seconds{duration})) - { - fee_.update(Resource::kFeeInvalidData, "squelch duration"); - } - - JLOG(pJournal_.debug()) << "onMessage: TMSquelch " << slice << " " << id() << " " << duration; + JLOG(self->pJournal_.debug()) + << "onMessage: TMSquelch " << slice << " " << self->id() << " " << duration; + }); } //-------------------------------------------------------------------------- From 0b22050b5e33e5a46e0a294124f547cd5fd6da49 Mon Sep 17 00:00:00 2001 From: Jingchen Date: Tue, 23 Jun 2026 20:25:38 +0100 Subject: [PATCH 02/14] ci: Update workflows and conan to use VS2026 and grpc 1.81.0 (#7550) Co-authored-by: Ayaz Salikhov --- .github/scripts/strategy-matrix/windows.json | 2 +- .github/workflows/reusable-build-test-config.yml | 4 ++-- conan.lock | 12 ++++++------ conanfile.py | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/scripts/strategy-matrix/windows.json b/.github/scripts/strategy-matrix/windows.json index e25f9ad131..370e9f5bc7 100644 --- a/.github/scripts/strategy-matrix/windows.json +++ b/.github/scripts/strategy-matrix/windows.json @@ -1,6 +1,6 @@ { "platform": "windows/amd64", - "runner": ["self-hosted", "Windows", "devbox"], + "runner": ["self-hosted", "Windows", "dev-box-windows-2026"], "configs": [ { "build_type": "Release" }, { diff --git a/.github/workflows/reusable-build-test-config.yml b/.github/workflows/reusable-build-test-config.yml index 3e6464aaba..fe441dba6e 100644 --- a/.github/workflows/reusable-build-test-config.yml +++ b/.github/workflows/reusable-build-test-config.yml @@ -82,7 +82,7 @@ jobs: name: ${{ inputs.config_name }} runs-on: ${{ fromJSON(inputs.runs_on) }} container: ${{ inputs.image != '' && inputs.image || null }} - timeout-minutes: ${{ inputs.sanitizers != '' && 360 || 90 }} + timeout-minutes: ${{ inputs.sanitizers != '' && 360 || 180 }} env: # Use a namespace to keep the objects separate for each configuration. CCACHE_NAMESPACE: ${{ inputs.config_name }} @@ -163,7 +163,7 @@ jobs: CMAKE_ARGS: ${{ inputs.cmake_args }} run: | cmake \ - -G '${{ runner.os == 'Windows' && 'Visual Studio 17 2022' || 'Ninja' }}' \ + -G '${{ runner.os == 'Windows' && 'Visual Studio 18 2026' || 'Ninja' }}' \ -DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \ -DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \ ${CMAKE_ARGS} \ diff --git a/conan.lock b/conan.lock index e2eb8d871a..d80a6d0c57 100644 --- a/conan.lock +++ b/conan.lock @@ -1,9 +1,9 @@ { "version": "0.5", "requires": [ - "zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1777558780.503", + "zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1778091116.056", "xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1765850149.987", - "sqlite3/3.53.0#324ada52333108388a9a6108bfa96734%1776096494.149", + "sqlite3/3.53.0#324ada52333108388a9a6108bfa96734%1778091117.311", "soci/4.0.3#fe32b9ad5eb47e79ab9e45a68f363945%1774450067.231", "snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1765850147.878", "secp256k1/0.7.1#481881709eb0bdd0185a12b912bbe8ad%1770910500.329", @@ -15,19 +15,19 @@ "lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1765850143.914", "libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1765842973.492", "libbacktrace/cci.20210118#a7691bfccd8caaf66309df196790a5a1%1765842973.03", - "libarchive/3.8.7#c446109bd1f1d8ba7936c94189bc50e6%1776147552.838", + "libarchive/3.8.7#c446109bd1f1d8ba7936c94189bc50e6%1778091117.848", "jemalloc/5.3.1#1fc58d55316041f10fbc1e8a2eae632a%1776700028.228", "gtest/1.17.0#5224b3b3ff3b4ce1133cbdd27d53ee7d%1768312129.152", - "grpc/1.78.1#b1a9e74b145cc471bed4dc64dc6eb2c1%1774467387.342", + "grpc/1.81.0#2fb144aeb47e7f35c6ebb0e5f35bed31%1781620605.685", "ed25519/2015.03#ae761bdc52730a843f0809bdf6c1b1f6%1765850143.772", "date/3.0.4#862e11e80030356b53c2c38599ceb32b%1765850143.772", "c-ares/1.34.6#545240bb1c40e2cacd4362d6b8967650%1774439234.681", "bzip2/1.0.8#c470882369c2d95c5c77e970c0c7e321%1765850143.837", - "boost/1.91.0#ea540ca2133d831b560036aa24dece3c%1778050991.9", + "boost/1.91.0#ea540ca2133d831b560036aa24dece3c%1778091165.282", "abseil/20250127.0#bb0baf1f362bc4a725a24eddd419b8f7%1774365460.196" ], "build_requires": [ - "zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1777558780.503", + "zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1778091116.056", "strawberryperl/5.32.1.1#8d114504d172cfea8ea1662d09b6333e%1774447376.964", "protobuf/6.33.5#d96d52ba5baaaa532f47bda866ad87a5%1774467363.12", "nasm/2.16.01#31e26f2ee3c4346ecd347911bd126904%1765850144.707", diff --git a/conanfile.py b/conanfile.py index 2cf5aefbc2..5b78dc22e3 100644 --- a/conanfile.py +++ b/conanfile.py @@ -28,7 +28,7 @@ class Xrpl(ConanFile): requires = [ "ed25519/2015.03", - "grpc/1.78.1", + "grpc/1.81.0", "libarchive/3.8.7", "nudb/2.0.9", "openssl/3.6.2", From 5a2c82f699f1d5036f572d771e7be597ba80f896 Mon Sep 17 00:00:00 2001 From: yinyiqian1 Date: Tue, 23 Jun 2026 15:55:23 -0400 Subject: [PATCH 03/14] fix: Reject delegate permission to pseudo accounts (#7597) --- src/libxrpl/tx/transactors/delegate/DelegateSet.cpp | 6 +++++- src/test/app/Delegate_test.cpp | 13 +++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/libxrpl/tx/transactors/delegate/DelegateSet.cpp b/src/libxrpl/tx/transactors/delegate/DelegateSet.cpp index 82fe88aa9f..32a51555b1 100644 --- a/src/libxrpl/tx/transactors/delegate/DelegateSet.cpp +++ b/src/libxrpl/tx/transactors/delegate/DelegateSet.cpp @@ -52,9 +52,13 @@ DelegateSet::preclaim(PreclaimContext const& ctx) if (!ctx.view.exists(keylet::account(ctx.tx[sfAccount]))) return terNO_ACCOUNT; // LCOV_EXCL_LINE - if (!ctx.view.exists(keylet::account(ctx.tx[sfAuthorize]))) + auto const sleAuthorize = ctx.view.read(keylet::account(ctx.tx[sfAuthorize])); + if (!sleAuthorize) return tecNO_TARGET; + if (isPseudoAccount(sleAuthorize)) + return tecNO_PERMISSION; + // Deleting the delegate object is invalid if it doesn’t exist. if (ctx.tx.getFieldArray(sfPermissions).empty() && !ctx.view.exists(keylet::delegate(ctx.tx[sfAccount], ctx.tx[sfAuthorize]))) diff --git a/src/test/app/Delegate_test.cpp b/src/test/app/Delegate_test.cpp index 20668a42bf..1516219e46 100644 --- a/src/test/app/Delegate_test.cpp +++ b/src/test/app/Delegate_test.cpp @@ -235,6 +235,19 @@ class Delegate_test : public beast::unit_test::Suite env(delegate::set(gw, Account("unknown"), {"Payment"}), Ter(tecNO_TARGET)); } + // Delegating to a pseudo-account is not allowed, should return tecNO_PERMISSION + { + Vault const vault{env}; + auto [tx, keylet] = vault.create({.owner = gw, .asset = xrpIssue()}); + env(tx); + env.close(); + + auto const sleVault = env.le(keylet); + BEAST_EXPECT(sleVault); + Account const vaultPseudo{"vault", sleVault->at(sfAccount)}; + env(delegate::set(gw, vaultPseudo, {"Payment"}), Ter(tecNO_PERMISSION)); + } + // non-delegable transaction { env(delegate::set(gw, alice, {"SetRegularKey"}), Ter(temMALFORMED)); From 6341e752002f90dc87ed49650cb704eac5f62660 Mon Sep 17 00:00:00 2001 From: Jingchen Date: Wed, 24 Jun 2026 13:15:11 +0100 Subject: [PATCH 04/14] refactor: Refactor TaggedCache.ipp to remove const_cast in canonicalize_replace_cache (#5638) Signed-off-by: JCW Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: xrplf-ai-reviewer[bot] <266832837+xrplf-ai-reviewer[bot]@users.noreply.github.com> --- include/xrpl/basics/TaggedCache.h | 86 +++++++++++++++++++-- include/xrpl/basics/TaggedCache.ipp | 87 +++++++++++++++++---- src/test/basics/TaggedCache_test.cpp | 110 +++++++++++++++++++++++++++ 3 files changed, 264 insertions(+), 19 deletions(-) diff --git a/include/xrpl/basics/TaggedCache.h b/include/xrpl/basics/TaggedCache.h index 380b7c687f..ecf6071f8d 100644 --- a/include/xrpl/basics/TaggedCache.h +++ b/include/xrpl/basics/TaggedCache.h @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -17,6 +18,22 @@ namespace xrpl { +namespace detail { + +// Replace-policy tags selecting how TaggedCache::canonicalizeImpl resolves a +// collision when the key already exists (defined in TaggedCache.ipp): +// - ReplaceCached: always replace the cached value with `data`. `data` is +// never written back and may be const. +// - ReplaceClient: keep the cached value and write it back into `data` (the +// client's pointer), which must therefore be writable. +// - ReplaceDynamically: call the supplied callback to decide per call; `data` +// is written back when the cached value is kept, so it must be writable. +struct ReplaceCached; +struct ReplaceClient; +struct ReplaceDynamically; + +} // namespace detail + /** Map/cache combination. This class implements a cache and a map. The cache keeps objects alive in the map. The map allows multiple code paths that reference objects @@ -96,6 +113,32 @@ public: bool del(key_type const& key, bool valid); +private: + // Selects the `data` parameter type of canonicalizeImpl from the replace + // policy: const for detail::ReplaceCached (never written back), otherwise + // writable. + template + using CanonicalizeClientPointerType = std::conditional_t< + std::is_same_v, + SharedPointerType const&, + SharedPointerType&>; + + /** Shared implementation of the canonicalize family. + + `policy` selects how a collision is resolved when `key` already exists: + detail::ReplaceCached, detail::ReplaceClient or + detail::ReplaceDynamically. For ReplaceDynamically `replaceCallback` is + invoked with the existing strong pointer and returns whether to replace + the cached value with `data`; for the tag policies it is unused. + */ + template + bool + canonicalizeImpl( + key_type const& key, + CanonicalizeClientPointerType data, + Policy policy, + Callback&& replaceCallback = nullptr); + public: /** Replace aliased objects with originals. @@ -104,19 +147,52 @@ public: This routine eliminates the duplicate and performs a replacement on the callers shared pointer if needed. + `replaceCallback` is a callable taking the existing strong pointer and + returning whether to replace the cached value with `data` (true) or to + keep the cached value and write it back into `data` (false). Because the + write-back case mutates `data`, `data` must be writable. + @param key The key corresponding to the object @param data A shared pointer to the data corresponding to the object. - @param replace Function that decides if cache should be replaced + @param replaceCallback A callable (existing strong pointer -> bool). - @return `true` If the key already existed. - */ - template + @return `true` if an existing live entry was found and used; `false` if a new entry was + inserted or an expired tracked entry was re-cached. + **/ + template bool - canonicalize(key_type const& key, SharedPointerType& data, R&& replaceCallback); + canonicalize(key_type const& key, SharedPointerType& data, Callback&& replaceCallback); + /** Insert/update the canonical entry for `key`, always replacing the + cached value with `data`. + + If an entry already exists for `key`, the cached value is unconditionally + replaced with `data`; otherwise `data` is inserted. `data` is never + written back, so it may be const. + + @param key The key corresponding to the object. + @param data A shared pointer to the data corresponding to the object. + + @return `true` if an existing live entry was found and used; `false` if a new entry was + inserted or an expired tracked entry was re-cached. + **/ bool canonicalizeReplaceCache(key_type const& key, SharedPointerType const& data); + /** Insert the canonical entry for `key`, keeping any existing cached value. + + If an entry already exists for `key`, the cached value is kept and + written back into `data` so the caller ends up with the canonical + object; otherwise `data` is inserted. Because `data` may be overwritten + it must be writable. + + @param key The key corresponding to the object. + @param data A shared pointer to the data corresponding to the object; + updated to the canonical value when one already exists. + + @return `true` if an existing live entry was found and used; `false` if a new entry was + inserted or an expired tracked entry was re-cached. + **/ bool canonicalizeReplaceClient(key_type const& key, SharedPointerType& data); diff --git a/include/xrpl/basics/TaggedCache.ipp b/include/xrpl/basics/TaggedCache.ipp index cee02749c6..6973ec4ba0 100644 --- a/include/xrpl/basics/TaggedCache.ipp +++ b/include/xrpl/basics/TaggedCache.ipp @@ -5,6 +5,30 @@ namespace xrpl { +namespace detail { + +// Replace-policy tags selecting how TaggedCache::canonicalizeImpl resolves a +// collision when the key already exists: +// - ReplaceCached: always replace the cached value with `data`. `data` is +// never written back and may be const. +// - ReplaceClient: keep the cached value and write it back into `data` (the +// client's pointer), which must therefore be writable. +// - ReplaceDynamically: call the supplied callback to decide per call; `data` +// is written back when the cached value is kept, so it must be writable. +struct ReplaceCached +{ +}; + +struct ReplaceClient +{ +}; + +struct ReplaceDynamically +{ +}; + +} // namespace detail + template < class Key, class T, @@ -300,13 +324,29 @@ template < class Hash, class KeyEqual, class Mutex> -template +template inline bool TaggedCache:: - canonicalize(key_type const& key, SharedPointerType& data, R&& replaceCallback) + canonicalizeImpl( + key_type const& key, + CanonicalizeClientPointerType data, + [[maybe_unused]] Policy policy, + [[maybe_unused]] Callback&& replaceCallback) { // Return canonical value, store if needed, refresh in cache // Return values: true=we had the data already + + // `Policy` is one of: + // - detail::ReplaceCached: always replace the cached value with `data`; + // `data` is never written back and may be const. + // - detail::ReplaceClient: keep the cached value and write it back into + // `data` (the client's pointer), which must therefore be writable. + // - detail::ReplaceDynamically: call `replaceCallback` to decide at run + // time; `data` must be writable. + // For the latter two the write-back below requires a mutable `data`, so + // passing a const argument is a compile error. + constexpr bool replaceCached = std::is_same_v; + std::scoped_lock const lock(mutex_); auto cit = cache_.find(key); @@ -324,13 +364,14 @@ TaggedCachesecond; entry.touch(clock_.now()); - auto shouldReplace = [&] { - if constexpr (std::is_invocable_r_v) + auto shouldReplaceCached = [&] { + if constexpr (replaceCached) { - // The reason for this extra complexity is for intrusive - // strong/weak combo getting a strong is relatively expensive - // and not needed for many cases. - return replaceCallback(); + return true; + } + else if constexpr (std::is_same_v) + { + return false; } else { @@ -340,11 +381,11 @@ TaggedCache +template +inline bool +TaggedCache:: + canonicalize(key_type const& key, SharedPointerType& data, Callback&& replaceCallback) +{ + return canonicalizeImpl( + key, data, detail::ReplaceDynamically{}, std::forward(replaceCallback)); +} + template < class Key, class T, @@ -389,7 +448,7 @@ inline bool TaggedCache:: canonicalizeReplaceCache(key_type const& key, SharedPointerType const& data) { - return canonicalize(key, const_cast(data), []() { return true; }); + return canonicalizeImpl(key, data, detail::ReplaceCached{}); } template < @@ -405,7 +464,7 @@ inline bool TaggedCache:: canonicalizeReplaceClient(key_type const& key, SharedPointerType& data) { - return canonicalize(key, data, []() { return false; }); + return canonicalizeImpl(key, data, detail::ReplaceClient{}); } template < diff --git a/src/test/basics/TaggedCache_test.cpp b/src/test/basics/TaggedCache_test.cpp index 77cd25e543..26564a4de8 100644 --- a/src/test/basics/TaggedCache_test.cpp +++ b/src/test/basics/TaggedCache_test.cpp @@ -1,5 +1,7 @@ #include +#include +#include #include #include // IWYU pragma: keep #include @@ -8,6 +10,7 @@ #include #include +#include namespace xrpl { @@ -133,6 +136,113 @@ public: BEAST_EXPECT(c.getCacheSize() == 0); BEAST_EXPECT(c.getTrackSize() == 0); } + { + BEAST_EXPECT(!c.insert(5, "five")); + BEAST_EXPECT(c.getCacheSize() == 1); + BEAST_EXPECT(c.size() == 1); + + { + auto const p1 = c.fetch(5); + BEAST_EXPECT(p1 != nullptr); + BEAST_EXPECT(c.getCacheSize() == 1); + BEAST_EXPECT(c.size() == 1); + + // Advance the clock a lot + ++clock; + c.sweep(); + BEAST_EXPECT(c.getCacheSize() == 0); + BEAST_EXPECT(c.size() == 1); + + auto p2 = std::make_shared("five_2"); + BEAST_EXPECT(c.canonicalizeReplaceCache(5, p2)); + BEAST_EXPECT(c.getCacheSize() == 1); + BEAST_EXPECT(c.size() == 1); + // Make sure the caller's original pointer is unchanged + BEAST_EXPECT(p1.get() != p2.get()); + BEAST_EXPECT(*p2 == "five_2"); + + auto const p3 = c.fetch(5); + BEAST_EXPECT(p3 != nullptr); + BEAST_EXPECT(p3.get() == p2.get()); + BEAST_EXPECT(p3.get() != p1.get()); + } + + ++clock; + c.sweep(); + BEAST_EXPECT(c.getCacheSize() == 0); + BEAST_EXPECT(c.size() == 0); + } + + { + testcase("intrptr"); + + struct MyRefCountObject : IntrusiveRefCounts + { + std::string data; + + // Needed to support weak intrusive pointers + virtual void + partialDestructor() {}; + + MyRefCountObject() = default; + explicit MyRefCountObject(std::string data) : data(std::move(data)) + { + } + + bool + operator==(std::string const& other) const + { + return data == other; + } + }; + + using IntrPtrCache = TaggedCache< + Key, + MyRefCountObject, + /*IsKeyCache*/ false, + intr_ptr::SharedWeakUnionPtr, + intr_ptr::SharedPtr>; + + IntrPtrCache intrPtrCache("IntrPtrTest", 1, 1s, clock, journal); + + intrPtrCache.canonicalizeReplaceCache(1, intr_ptr::makeShared("one")); + BEAST_EXPECT(intrPtrCache.getCacheSize() == 1); + BEAST_EXPECT(intrPtrCache.size() == 1); + + { + { + intrPtrCache.canonicalizeReplaceCache( + 1, intr_ptr::makeShared("one_replaced")); + + auto p = intrPtrCache.fetch(1); + BEAST_EXPECT(*p == "one_replaced"); + + // Advance the clock a lot + ++clock; + intrPtrCache.sweep(); + BEAST_EXPECT(intrPtrCache.getCacheSize() == 0); + BEAST_EXPECT(intrPtrCache.size() == 1); + + intrPtrCache.canonicalizeReplaceCache( + 1, intr_ptr::makeShared("one_replaced_2")); + + auto p2 = intrPtrCache.fetch(1); + BEAST_EXPECT(*p2 == "one_replaced_2"); + + intrPtrCache.del(1, true); + } + + intrPtrCache.canonicalizeReplaceCache( + 1, intr_ptr::makeShared("one_replaced_3")); + auto p3 = intrPtrCache.fetch(1); + BEAST_EXPECT(*p3 == "one_replaced_3"); + } + + ++clock; + intrPtrCache.sweep(); + BEAST_EXPECT(intrPtrCache.getCacheSize() == 0); + BEAST_EXPECT(intrPtrCache.size() == 0); + } } }; From 69d289a388f7339470e861cee38b29a877ee26a3 Mon Sep 17 00:00:00 2001 From: Zhiyuan Wang <96991820+Kassaking7@users.noreply.github.com> Date: Wed, 24 Jun 2026 08:15:45 -0400 Subject: [PATCH 05/14] fix: AMM Quality Leak into Domain BookStep for Permissioned DEX (#6853) Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- src/libxrpl/tx/paths/BookStep.cpp | 5 ++ src/test/app/PermissionedDEX_test.cpp | 79 +++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/src/libxrpl/tx/paths/BookStep.cpp b/src/libxrpl/tx/paths/BookStep.cpp index 5cc2a987b8..4b045521d2 100644 --- a/src/libxrpl/tx/paths/BookStep.cpp +++ b/src/libxrpl/tx/paths/BookStep.cpp @@ -905,6 +905,11 @@ BookStep::getAMMOffer( ReadView const& view, std::optional const& clobQuality) const { + // AMM doesn't support domain books. When fixCleanup3_3_0 is enabled, exclude + // AMM liquidity so quality estimation matches actual crossing (tryAMM skips + // AMM for domain books). + if (book_.domain && view.rules().enabled(fixCleanup3_3_0)) + return std::nullopt; if (ammLiquidity_) return ammLiquidity_->getOffer(view, clobQuality); return std::nullopt; diff --git a/src/test/app/PermissionedDEX_test.cpp b/src/test/app/PermissionedDEX_test.cpp index 99e69ce482..51ca321f7e 100644 --- a/src/test/app/PermissionedDEX_test.cpp +++ b/src/test/app/PermissionedDEX_test.cpp @@ -993,6 +993,83 @@ class PermissionedDEX_test : public beast::unit_test::Suite BEAST_EXPECT(usd == USD(45)); } + void + testAmmQualityNotLeaked(FeatureBitset features) + { + bool const excludesAmmFromDomainQuality = features[fixCleanup3_3_0]; + + testcase << "AMM quality not leaked into domain BookStep" + << (excludesAmmFromDomainQuality ? " (Cleanup3_3_0 enabled)" + : " (Cleanup3_3_0 disabled)"); + + Env env(*this, features); + auto const& [gw, domainOwner, alice, bob, carol, USD, domainID, credType] = + PermissionedDEX(env); + auto const eur = gw["EUR"]; + + env.trust(eur(1000), bob, domainOwner); + env.close(); + env(pay(gw, bob, eur(100))); + env.close(); + + env(pay(gw, alice, USD(500))); + env.close(); + + // The AMM makes the direct XRP->USD book look much better than it + // really is for domain payments. The domain LOB direct path is 1:1, + // while the competing XRP->EUR->USD path is 2:1. + AMM const amm(env, alice, XRP(10), USD(500)); + + auto const directOfferSeq{env.seq(bob)}; + env(offer(bob, XRP(10), USD(10)), Domain(domainID)); + env.close(); + + auto const xrpEurOfferSeq{env.seq(bob)}; + env(offer(bob, XRP(10), eur(20)), Domain(domainID)); + env.close(); + + auto const eurUsdOfferSeq{env.seq(domainOwner)}; + env(offer(domainOwner, eur(20), USD(20)), Domain(domainID)); + env.close(); + + auto const carolBalBefore = env.balance(carol, USD); + + // Both paths compete for the same XRP(10) sendmax. If AMM quality leaks + // into the direct domain book, the engine ranks direct XRP->USD first + // but crossing can only consume the 1:1 LOB offer. With the fix, the + // direct book is ranked by its domain LOB quality, so the 2:1 + // XRP->EUR->USD path executes first. + env(pay(alice, carol, USD(100)), + Path(~USD), + Path(~eur, ~USD), + Sendmax(XRP(10)), + Txflags(tfPartialPayment | tfNoRippleDirect), + Domain(domainID)); + env.close(); + + auto const delivered = env.balance(carol, USD) - carolBalBefore; + if (excludesAmmFromDomainQuality) + { + BEAST_EXPECT(delivered == USD(20)); + + BEAST_EXPECT(checkOffer(env, bob, directOfferSeq, XRP(10), USD(10), 0, true)); + BEAST_EXPECT(!offerExists(env, bob, xrpEurOfferSeq)); + BEAST_EXPECT(!offerExists(env, domainOwner, eurUsdOfferSeq)); + } + else + { + BEAST_EXPECT(delivered == USD(10)); + + BEAST_EXPECT(!offerExists(env, bob, directOfferSeq)); + BEAST_EXPECT(checkOffer(env, bob, xrpEurOfferSeq, XRP(10), eur(20), 0, true)); + BEAST_EXPECT(checkOffer(env, domainOwner, eurUsdOfferSeq, eur(20), USD(20), 0, true)); + } + + auto [xrp, usd, lpt] = amm.balances(XRP, USD); + BEAST_EXPECT(xrp == XRP(10)); + BEAST_EXPECT(usd == USD(500)); + } + void testHybridOfferCreate(FeatureBitset features) { @@ -1943,6 +2020,8 @@ public: testOfferTokenIssuerInDomain(all); testRemoveUnfundedOffer(all); testAmmNotUsed(all); + testAmmQualityNotLeaked(all); + testAmmQualityNotLeaked(all - fixCleanup3_3_0); testAutoBridge(all); // Test hybrid offers From bb7c4d1c9fdfd1267ac45198ff305545f9579a72 Mon Sep 17 00:00:00 2001 From: Timothy Banks Date: Wed, 24 Jun 2026 08:23:12 -0400 Subject: [PATCH 06/14] fix: Additional RPC validation checks on ammRpcInfo account and amm_account fields. (#7324) --- src/test/jtx/AMM.h | 14 +++++++-- src/test/jtx/impl/AMM.cpp | 30 +++++++++++++++++--- src/test/rpc/AMMInfo_test.cpp | 20 +++++++++++++ src/xrpld/rpc/handlers/orderbook/AMMInfo.cpp | 10 +++++-- 4 files changed, 66 insertions(+), 8 deletions(-) diff --git a/src/test/jtx/AMM.h b/src/test/jtx/AMM.h index deadd80290..99131637bb 100644 --- a/src/test/jtx/AMM.h +++ b/src/test/jtx/AMM.h @@ -174,12 +174,22 @@ public: ammRpcInfo( std::optional const& account = std::nullopt, std::optional const& ledgerIndex = std::nullopt, - std::optional asset1 = std::nullopt, - std::optional asset2 = std::nullopt, + std::optional const& asset1 = std::nullopt, + std::optional const& asset2 = std::nullopt, std::optional const& ammAccount = std::nullopt, bool ignoreParams = false, unsigned apiVersion = RPC::kApiInvalidVersion) const; + [[nodiscard]] json::Value + ammRpcInfo( + std::optional const& account, + std::optional const& ledgerIndex, + std::optional const& asset1, + std::optional const& asset2, + std::optional const& ammAccount, + bool ignoreParams, + unsigned apiVersion) const; + /** Verify the AMM balances. */ [[nodiscard]] bool diff --git a/src/test/jtx/impl/AMM.cpp b/src/test/jtx/impl/AMM.cpp index c6dc14081a..2184f7e1b0 100644 --- a/src/test/jtx/impl/AMM.cpp +++ b/src/test/jtx/impl/AMM.cpp @@ -183,15 +183,37 @@ json::Value AMM::ammRpcInfo( std::optional const& account, std::optional const& ledgerIndex, - std::optional asset1, - std::optional asset2, + std::optional const& asset1, + std::optional const& asset2, std::optional const& ammAccount, bool ignoreParams, unsigned apiVersion) const +{ + auto const toJson = [](AccountID const& a) { return json::Value{to_string(a)}; }; + + return ammRpcInfo( + account.transform(toJson), + ledgerIndex, + asset1, + asset2, + ammAccount.transform(toJson), + ignoreParams, + apiVersion); +} + +json::Value +AMM::ammRpcInfo( + std::optional const& account, + std::optional const& ledgerIndex, + std::optional const& asset1, + std::optional const& asset2, + std::optional const& ammAccount, + bool ignoreParams, + unsigned apiVersion) const { json::Value jv; if (account) - jv[jss::account] = to_string(*account); + jv[jss::account] = *account; if (ledgerIndex) jv[jss::ledger_index] = *ledgerIndex; if (!ignoreParams) @@ -209,7 +231,7 @@ AMM::ammRpcInfo( jv[jss::asset2] = STIssue(sfAsset2, asset2_.asset()).getJson(JsonOptions::Values::None); } if (ammAccount) - jv[jss::amm_account] = to_string(*ammAccount); + jv[jss::amm_account] = *ammAccount; } auto jr = (apiVersion == RPC::kApiInvalidVersion diff --git a/src/test/rpc/AMMInfo_test.cpp b/src/test/rpc/AMMInfo_test.cpp index 28c536aab9..987df6c724 100644 --- a/src/test/rpc/AMMInfo_test.cpp +++ b/src/test/rpc/AMMInfo_test.cpp @@ -65,6 +65,26 @@ public: BEAST_EXPECT(jv[jss::error_message] == "Account malformed."); }); + // Account is not a string + testAMM([&](AMM& ammAlice, Env&) { + auto const jv = + ammAlice.ammRpcInfo(json::Value{42}, std::nullopt, XRP, USD, std::nullopt, true, 3); + BEAST_EXPECT(jv[jss::error_message] == "Account malformed."); + }); + + // AMM Account is not a string + testAMM([&](AMM& ammAlice, Env&) { + auto const jv = ammAlice.ammRpcInfo( + json::Value{to_string(ammAlice.ammAccount())}, + std::nullopt, + XRP, + USD, + json::Value{42}, + false, + 3); + BEAST_EXPECT(jv[jss::error_message] == "Account malformed."); + }); + std::vector, std::optional, TestAccount, bool>> const invalidParams = { {xrpIssue(), std::nullopt, TestAccount::None, false}, diff --git a/src/xrpld/rpc/handlers/orderbook/AMMInfo.cpp b/src/xrpld/rpc/handlers/orderbook/AMMInfo.cpp index 2c2f96b0e8..043fdd2d7b 100644 --- a/src/xrpld/rpc/handlers/orderbook/AMMInfo.cpp +++ b/src/xrpld/rpc/handlers/orderbook/AMMInfo.cpp @@ -120,7 +120,10 @@ doAMMInfo(RPC::JsonContext& context) if (params.isMember(jss::amm_account)) { - auto const id = parseBase58((params[jss::amm_account].asString())); + auto const& ammAccount = params[jss::amm_account]; + if (!ammAccount.isString()) + return std::unexpected(RpcActMalformed); + auto const id = parseBase58(ammAccount.asString()); if (!id) return std::unexpected(RpcActMalformed); auto const sle = ledger->read(keylet::account(*id)); @@ -133,7 +136,10 @@ doAMMInfo(RPC::JsonContext& context) if (params.isMember(jss::account)) { - accountID = parseBase58(params[jss::account].asString()); + auto const& localAccount = params[jss::account]; + if (!localAccount.isString()) + return std::unexpected(RpcActMalformed); + accountID = parseBase58(localAccount.asString()); if (!accountID || !ledger->read(keylet::account(*accountID))) return std::unexpected(RpcActMalformed); } From b68e1f7170fd0de7b7b7110677919eb9df1773c2 Mon Sep 17 00:00:00 2001 From: Ayaz Salikhov Date: Wed, 24 Jun 2026 13:24:04 +0100 Subject: [PATCH 07/14] fix: Add pragma once checker (#7580) --- .pre-commit-config.yaml | 8 ++++- bin/pre-commit/fix_pragma_once.py | 34 +++++++++++++++++++ .../ledger/helpers/PermissionedDEXHelpers.h | 1 + include/xrpl/protocol/Batch.h | 2 ++ include/xrpl/tx/paths/detail/AmountSpec.h | 0 include/xrpl/tx/paths/detail/FlowDebugInfo.h | 1 - include/xrpl/tx/paths/detail/StrandFlow.h | 1 - src/libxrpl/tx/paths/Flow.cpp | 1 - src/libxrpl/tx/paths/XRPEndpointStep.cpp | 1 - src/libxrpl/tx/transactors/escrow/Escrow.cpp | 0 src/test/beast/IPEndpointCommon.h | 2 ++ src/test/csf.h | 2 ++ src/test/unit_test/utils.h | 2 ++ src/xrpld/app/ledger/OrderBookDB.h | 0 src/xrpld/overlay/detail/Tuning.h | 1 + src/xrpld/rpc/detail/PathRequestManager.h | 1 - src/xrpld/rpc/detail/Pathfinder.cpp | 1 - src/xrpld/rpc/detail/RippleLineCache.cpp | 0 src/xrpld/rpc/detail/RippleLineCache.h | 0 .../rpc/handlers/ledger/LedgerEntryHelpers.h | 2 ++ 20 files changed, 53 insertions(+), 7 deletions(-) create mode 100755 bin/pre-commit/fix_pragma_once.py delete mode 100644 include/xrpl/tx/paths/detail/AmountSpec.h delete mode 100644 src/libxrpl/tx/transactors/escrow/Escrow.cpp delete mode 100644 src/xrpld/app/ledger/OrderBookDB.h delete mode 100644 src/xrpld/rpc/detail/RippleLineCache.cpp delete mode 100644 src/xrpld/rpc/detail/RippleLineCache.h diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c9dec89435..4cbf4c1dd0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,6 +15,7 @@ repos: hooks: - id: check-added-large-files args: [--maxkb=400, --enforce-all] + - id: check-executables-have-shebangs - id: trailing-whitespace - id: end-of-file-fixer - id: check-merge-conflict @@ -35,13 +36,18 @@ repos: language: python types_or: [c++, c] exclude: ^include/xrpl/protocol_autogen/(transactions|ledger_entries)/ + - id: fix-pragma-once + name: fix missing '#pragma once' declarations in header files + language: python + entry: ./bin/pre-commit/fix_pragma_once.py + files: \.(h|hpp)$ - repo: https://github.com/pre-commit/mirrors-clang-format rev: dd18dad857d6133e90bbe478f4f2f22ec0030269 # frozen: v22.1.5 hooks: - id: clang-format args: [--style=file] - "types_or": [c++, c, proto] + types_or: [c++, c, proto] exclude: ^include/xrpl/protocol_autogen/(transactions|ledger_entries)/ - repo: https://github.com/BlankSpruce/gersemi-pre-commit diff --git a/bin/pre-commit/fix_pragma_once.py b/bin/pre-commit/fix_pragma_once.py new file mode 100755 index 0000000000..08a505b6d0 --- /dev/null +++ b/bin/pre-commit/fix_pragma_once.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 + +""" +Adds "#pragma once" to the top of header files that don't already have it. + +Usage: ./bin/pre-commit/fix_pragma_once.py ... +""" + +import sys +from pathlib import Path + +PRAGMA_ONCE = "#pragma once\n\n" + + +def fix_pragma_once(path: Path) -> bool: + original = path.read_text(encoding="utf-8") + if PRAGMA_ONCE not in original: + path.write_text(PRAGMA_ONCE + original, encoding="utf-8") + return False + return True + + +def main() -> int: + files = [Path(f) for f in sys.argv[1:]] + success = True + + for path in files: + success &= fix_pragma_once(path) + + return 0 if success else 1 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/include/xrpl/ledger/helpers/PermissionedDEXHelpers.h b/include/xrpl/ledger/helpers/PermissionedDEXHelpers.h index 04b12f2fc5..695a4950f0 100644 --- a/include/xrpl/ledger/helpers/PermissionedDEXHelpers.h +++ b/include/xrpl/ledger/helpers/PermissionedDEXHelpers.h @@ -1,4 +1,5 @@ #pragma once + #include namespace xrpl::permissioned_dex { diff --git a/include/xrpl/protocol/Batch.h b/include/xrpl/protocol/Batch.h index fa7641af70..2f2412b3ff 100644 --- a/include/xrpl/protocol/Batch.h +++ b/include/xrpl/protocol/Batch.h @@ -1,3 +1,5 @@ +#pragma once + #include #include #include diff --git a/include/xrpl/tx/paths/detail/AmountSpec.h b/include/xrpl/tx/paths/detail/AmountSpec.h deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/include/xrpl/tx/paths/detail/FlowDebugInfo.h b/include/xrpl/tx/paths/detail/FlowDebugInfo.h index ec7df86e53..1ccfba34ce 100644 --- a/include/xrpl/tx/paths/detail/FlowDebugInfo.h +++ b/include/xrpl/tx/paths/detail/FlowDebugInfo.h @@ -3,7 +3,6 @@ #include #include #include -#include #include diff --git a/include/xrpl/tx/paths/detail/StrandFlow.h b/include/xrpl/tx/paths/detail/StrandFlow.h index 31f0182258..4d988a4c7e 100644 --- a/include/xrpl/tx/paths/detail/StrandFlow.h +++ b/include/xrpl/tx/paths/detail/StrandFlow.h @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include diff --git a/src/libxrpl/tx/paths/Flow.cpp b/src/libxrpl/tx/paths/Flow.cpp index 39a9e83e69..7be1f9f633 100644 --- a/src/libxrpl/tx/paths/Flow.cpp +++ b/src/libxrpl/tx/paths/Flow.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include diff --git a/src/libxrpl/tx/paths/XRPEndpointStep.cpp b/src/libxrpl/tx/paths/XRPEndpointStep.cpp index 314780c3a7..efdad92791 100644 --- a/src/libxrpl/tx/paths/XRPEndpointStep.cpp +++ b/src/libxrpl/tx/paths/XRPEndpointStep.cpp @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include diff --git a/src/libxrpl/tx/transactors/escrow/Escrow.cpp b/src/libxrpl/tx/transactors/escrow/Escrow.cpp deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/test/beast/IPEndpointCommon.h b/src/test/beast/IPEndpointCommon.h index 15566cb830..0ff0da35be 100644 --- a/src/test/beast/IPEndpointCommon.h +++ b/src/test/beast/IPEndpointCommon.h @@ -1,3 +1,5 @@ +#pragma once + #include #include diff --git a/src/test/csf.h b/src/test/csf.h index 81af3491c4..d2ddbb460d 100644 --- a/src/test/csf.h +++ b/src/test/csf.h @@ -1,3 +1,5 @@ +#pragma once + #include #include #include diff --git a/src/test/unit_test/utils.h b/src/test/unit_test/utils.h index 028823c763..677bbff31b 100644 --- a/src/test/unit_test/utils.h +++ b/src/test/unit_test/utils.h @@ -1,3 +1,5 @@ +#pragma once + #include #include diff --git a/src/xrpld/app/ledger/OrderBookDB.h b/src/xrpld/app/ledger/OrderBookDB.h deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/xrpld/overlay/detail/Tuning.h b/src/xrpld/overlay/detail/Tuning.h index 20a60d470e..8357fcd130 100644 --- a/src/xrpld/overlay/detail/Tuning.h +++ b/src/xrpld/overlay/detail/Tuning.h @@ -1,4 +1,5 @@ #pragma once + #include #include diff --git a/src/xrpld/rpc/detail/PathRequestManager.h b/src/xrpld/rpc/detail/PathRequestManager.h index 5a5cfde402..c8e272a97d 100644 --- a/src/xrpld/rpc/detail/PathRequestManager.h +++ b/src/xrpld/rpc/detail/PathRequestManager.h @@ -3,7 +3,6 @@ #include #include #include -#include #include #include diff --git a/src/xrpld/rpc/detail/Pathfinder.cpp b/src/xrpld/rpc/detail/Pathfinder.cpp index 25da86ef8f..e1a2a4acf6 100644 --- a/src/xrpld/rpc/detail/Pathfinder.cpp +++ b/src/xrpld/rpc/detail/Pathfinder.cpp @@ -3,7 +3,6 @@ #include #include #include -#include #include #include diff --git a/src/xrpld/rpc/detail/RippleLineCache.cpp b/src/xrpld/rpc/detail/RippleLineCache.cpp deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/xrpld/rpc/detail/RippleLineCache.h b/src/xrpld/rpc/detail/RippleLineCache.h deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/xrpld/rpc/handlers/ledger/LedgerEntryHelpers.h b/src/xrpld/rpc/handlers/ledger/LedgerEntryHelpers.h index 463547a90d..11f6553dfa 100644 --- a/src/xrpld/rpc/handlers/ledger/LedgerEntryHelpers.h +++ b/src/xrpld/rpc/handlers/ledger/LedgerEntryHelpers.h @@ -1,3 +1,5 @@ +#pragma once + #include #include From 6736ab39df871bbb49107c0af8a2821fc3afebaf Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Wed, 24 Jun 2026 08:24:27 -0400 Subject: [PATCH 08/14] test: Add test for Permissioned Domain sequence fix (#7591) Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- src/test/app/PermissionedDomains_test.cpp | 46 +++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/test/app/PermissionedDomains_test.cpp b/src/test/app/PermissionedDomains_test.cpp index f2d7bce152..2cffc18682 100644 --- a/src/test/app/PermissionedDomains_test.cpp +++ b/src/test/app/PermissionedDomains_test.cpp @@ -8,18 +8,21 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -526,6 +529,47 @@ class PermissionedDomains_test : public beast::unit_test::Suite BEAST_EXPECT(env.ownerCount(alice) == 1); } + void + testTicket(FeatureBitset features) + { + testcase("Tickets"); + + using namespace test::jtx; + + Env env(*this, features); + Account const alice("alice"); + env.fund(XRP(1000), alice); + + pdomain::Credentials const credentials{ + {.issuer = alice, .credType = "credential1"}, + }; + + std::uint32_t seq{env.seq(alice)}; + env(ticket::create(alice, 2)); + + { + env(pdomain::setTx(alice, credentials), ticket::Use(++seq)); + auto domain = pdomain::getNewDomain(env.meta()); + if (features[fixCleanup3_1_3]) + { + BEAST_EXPECT(domain == keylet::permissionedDomain(alice.id(), seq).key); + } + else + { + BEAST_EXPECT(domain == keylet::permissionedDomain(alice.id(), 0).key); + } + } + + if (features[fixCleanup3_1_3]) + { + env(pdomain::setTx(alice, credentials), ticket::Use(++seq)); + } + else + { + env(pdomain::setTx(alice, credentials), ticket::Use(++seq), Ter(tefEXCEPTION)); + } + } + public: void run() override @@ -540,6 +584,8 @@ public: testDelete(withFix_); testAccountReserve(withFeature_); testAccountReserve(withFix_); + testTicket(withFeature_); + testTicket(withFix_); } }; From 8bbbc2051e04edb4d0959deb6c8b322e3e29a63e Mon Sep 17 00:00:00 2001 From: Ayaz Salikhov Date: Wed, 24 Jun 2026 13:25:03 +0100 Subject: [PATCH 09/14] chore: Check more tools to be available (#7600) --- .github/scripts/strategy-matrix/linux.json | 2 +- .github/workflows/on-pr.yml | 1 + .github/workflows/on-trigger.yml | 1 + .github/workflows/publish-docs.yml | 2 +- .github/workflows/reusable-clang-tidy.yml | 2 +- .github/workflows/reusable-upload-recipe.yml | 2 +- bin/check-tools.sh | 3 +++ 7 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/scripts/strategy-matrix/linux.json b/.github/scripts/strategy-matrix/linux.json index a9b85b766a..863b910dda 100644 --- a/.github/scripts/strategy-matrix/linux.json +++ b/.github/scripts/strategy-matrix/linux.json @@ -1,5 +1,5 @@ { - "image_tag": "sha-fe4c8ae", + "image_tag": "sha-e29b523", "configs": { "ubuntu": [ { diff --git a/.github/workflows/on-pr.yml b/.github/workflows/on-pr.yml index 0cc9b375a7..0c9eeda712 100644 --- a/.github/workflows/on-pr.yml +++ b/.github/workflows/on-pr.yml @@ -70,6 +70,7 @@ jobs: .github/workflows/reusable-upload-recipe.yml .clang-tidy .codecov.yml + bin/check-tools.sh cfg/** cmake/** conan/** diff --git a/.github/workflows/on-trigger.yml b/.github/workflows/on-trigger.yml index 74bca82019..063cdbff7f 100644 --- a/.github/workflows/on-trigger.yml +++ b/.github/workflows/on-trigger.yml @@ -27,6 +27,7 @@ on: - ".github/workflows/reusable-upload-recipe.yml" - ".clang-tidy" - ".codecov.yml" + - "bin/check-tools.sh" - "cfg/**" - "cmake/**" - "conan/**" diff --git a/.github/workflows/publish-docs.yml b/.github/workflows/publish-docs.yml index cc7b6b6e7e..cb7d4c5382 100644 --- a/.github/workflows/publish-docs.yml +++ b/.github/workflows/publish-docs.yml @@ -41,7 +41,7 @@ env: jobs: build: runs-on: ubuntu-latest - container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-fe4c8ae + container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-e29b523 steps: - name: Checkout repository uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 diff --git a/.github/workflows/reusable-clang-tidy.yml b/.github/workflows/reusable-clang-tidy.yml index e99ef574bf..f36463a5d0 100644 --- a/.github/workflows/reusable-clang-tidy.yml +++ b/.github/workflows/reusable-clang-tidy.yml @@ -39,7 +39,7 @@ jobs: needs: [determine-files] if: ${{ always() && !cancelled() && (!inputs.check_only_changed || needs.determine-files.outputs.cpp_changed_files != '' || needs.determine-files.outputs.clang_tidy_config_changed == 'true') }} runs-on: ["self-hosted", "Linux", "X64", "heavy"] - container: "ghcr.io/xrplf/xrpld/nix-debian:sha-fe4c8ae" + container: "ghcr.io/xrplf/xrpld/nix-debian:sha-e29b523" permissions: contents: read issues: write diff --git a/.github/workflows/reusable-upload-recipe.yml b/.github/workflows/reusable-upload-recipe.yml index a389e98771..a18f76796a 100644 --- a/.github/workflows/reusable-upload-recipe.yml +++ b/.github/workflows/reusable-upload-recipe.yml @@ -40,7 +40,7 @@ defaults: jobs: upload: runs-on: ubuntu-latest - container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-fe4c8ae + container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-e29b523 steps: - name: Checkout repository uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 diff --git a/bin/check-tools.sh b/bin/check-tools.sh index 15b16b6fc8..808f384d5b 100755 --- a/bin/check-tools.sh +++ b/bin/check-tools.sh @@ -90,16 +90,19 @@ if [ "${os}" = "linux" ] || [ "${os}" = "macos" ]; then check perl check pkg-config check vim + check zip # These tools are present in our Linux CI images and in local development # setups, but not in the macOS CI environment. So check them everywhere # except when running in CI on macOS. if [ "${os}" = "linux" ] || [ -z "${CI:-}" ]; then check clang-format + check dot check doxygen check gcovr check gh check git-cliff + check git-lfs check gpg # pre-commit, or its alternative implementation prek check pre-commit sh -c 'pre-commit --version || prek --version' From 4fec58251b8d20fd5356f08ed04ddc80d008c2bf Mon Sep 17 00:00:00 2001 From: Ayaz Salikhov Date: Wed, 24 Jun 2026 14:56:18 +0100 Subject: [PATCH 10/14] build: Patch nix binaries in CMake (#7539) Co-authored-by: Bart --- .gersemi/definitions.cmake | 3 ++ .../workflows/reusable-build-test-config.yml | 15 ------ CMakeLists.txt | 2 + cmake/CompilationEnv.cmake | 13 +++++ cmake/PatchNixBinary.cmake | 53 +++++++++++++++++++ cmake/XrplCompiler.cmake | 9 ++++ cmake/XrplCore.cmake | 1 + cmake/XrplSanitizers.cmake | 4 +- src/tests/libxrpl/CMakeLists.txt | 1 + 9 files changed, 83 insertions(+), 18 deletions(-) create mode 100644 cmake/PatchNixBinary.cmake diff --git a/.gersemi/definitions.cmake b/.gersemi/definitions.cmake index 245f827f90..58bc74c70a 100644 --- a/.gersemi/definitions.cmake +++ b/.gersemi/definitions.cmake @@ -96,3 +96,6 @@ function(verbose_find_path variable name) ${ARGN} ) endfunction() + +function(patch_nix_binary target) +endfunction() diff --git a/.github/workflows/reusable-build-test-config.yml b/.github/workflows/reusable-build-test-config.yml index fe441dba6e..a81d9aec67 100644 --- a/.github/workflows/reusable-build-test-config.yml +++ b/.github/workflows/reusable-build-test-config.yml @@ -229,21 +229,6 @@ jobs: --parallel "${BUILD_NPROC}" \ --target "${CMAKE_TARGET}" - # This step is needed to allow running in non-Nix environments - - name: Patch binary to use default loader and remove rpath (Linux) - if: ${{ runner.os == 'Linux' && env.SANITIZERS_ENABLED == 'false' }} - run: | - loader="$(/tmp/loader-path.sh)" - patchelf --set-interpreter "${loader}" --remove-rpath "${{ env.BUILD_DIR }}/xrpld" - - # We're only running aarch64 Linux builds in Ubuntu-based images, so this is kept simple - - name: Install libatomic (Linux aarch64) - if: ${{ runner.os == 'Linux' && runner.arch == 'ARM64' }} - run: | - apt update --yes - apt install -y --no-install-recommends \ - libatomic1 - - name: Show ccache statistics if: ${{ inputs.ccache_enabled }} run: | diff --git a/CMakeLists.txt b/CMakeLists.txt index 3dbe60a220..bdc62442b3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,6 +57,8 @@ if(target) ) endif() +include(PatchNixBinary) + include(XrplSanity) include(XrplVersion) include(XrplSettings) diff --git a/cmake/CompilationEnv.cmake b/cmake/CompilationEnv.cmake index 0d44f90974..8e69a4dfdd 100644 --- a/cmake/CompilationEnv.cmake +++ b/cmake/CompilationEnv.cmake @@ -56,3 +56,16 @@ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64|ARM64") else() message(FATAL_ERROR "Unknown architecture: ${CMAKE_SYSTEM_PROCESSOR}") endif() + +# -------------------------------------------------------------------- +# Sanitizers +# -------------------------------------------------------------------- +# SANITIZERS is injected by the Conan toolchain when a sanitizer build is +# requested (see conan/profiles/sanitizers). The flags are applied to the +# 'common' target in XrplSanitizers; this flag lets other modules know a +# sanitizer build is active without depending on that module. +if(DEFINED SANITIZERS) + set(SANITIZERS_ENABLED TRUE) +else() + set(SANITIZERS_ENABLED FALSE) +endif() diff --git a/cmake/PatchNixBinary.cmake b/cmake/PatchNixBinary.cmake new file mode 100644 index 0000000000..79ca0b150c --- /dev/null +++ b/cmake/PatchNixBinary.cmake @@ -0,0 +1,53 @@ +#[===================================================================[ + Patch executables to run in non-Nix environments. + + The Nix-based CI image links binaries against an ELF interpreter (loader) + that lives in the Nix store, so the resulting binaries don't run elsewhere + (including once installed from the .deb package). `patch_nix_binary` adds a + POST_BUILD step that resets the interpreter to the system default loader and + drops the rpath. + + This is only active inside the Nix-based image, detected by the presence of + /tmp/loader-path.sh (shipped by that image, resolves the default loader). It + is skipped for sanitizer builds, whose runtime libraries are resolved through + the rpath. Everywhere else `patch_nix_binary` is a no-op. +#]===================================================================] + +include_guard(GLOBAL) + +include(CompilationEnv) + +# Provided by the Nix-based CI image; prints the system default ELF loader path. +set(_loader_path_script "/tmp/loader-path.sh") + +if(is_linux AND NOT SANITIZERS_ENABLED AND EXISTS "${_loader_path_script}") + execute_process( + COMMAND "${_loader_path_script}" + OUTPUT_VARIABLE DEFAULT_LOADER_PATH + OUTPUT_STRIP_TRAILING_WHITESPACE + COMMAND_ERROR_IS_FATAL ANY + ) + find_program(PATCHELF_COMMAND patchelf REQUIRED) + set(PATCH_NIX_BINARIES TRUE) + message( + STATUS + "Binaries will be patched to use loader '${DEFAULT_LOADER_PATH}'" + ) +else() + set(PATCH_NIX_BINARIES FALSE) +endif() + +function(patch_nix_binary target) + if(NOT PATCH_NIX_BINARIES) + return() + endif() + add_custom_command( + TARGET ${target} + POST_BUILD + COMMAND + "${PATCHELF_COMMAND}" --set-interpreter "${DEFAULT_LOADER_PATH}" + --remove-rpath "$" + COMMENT "Patching ${target}: set default loader, remove rpath" + VERBATIM + ) +endfunction() diff --git a/cmake/XrplCompiler.cmake b/cmake/XrplCompiler.cmake index 9af8e962d0..cb4e797137 100644 --- a/cmake/XrplCompiler.cmake +++ b/cmake/XrplCompiler.cmake @@ -154,6 +154,15 @@ else() > ) + # On aarch64, libatomic is required for atomic operations. It is not needed on x86_64. + # Linking it statically on Linux + if(is_arm64 AND is_linux) + target_link_options( + common + INTERFACE -Wl,--push-state -Wl,-Bstatic -latomic -Wl,--pop-state + ) + endif() + # Keep -stdlib=libstdc++ off the compile commands, but preserve it for linking. # # Conan turns `compiler.libcxx=libstdc++` into `-stdlib=libstdc++` and puts it in diff --git a/cmake/XrplCore.cmake b/cmake/XrplCore.cmake index 52d7714a99..4d4a800d9a 100644 --- a/cmake/XrplCore.cmake +++ b/cmake/XrplCore.cmake @@ -247,6 +247,7 @@ target_link_modules( if(xrpld) add_executable(xrpld) + patch_nix_binary(xrpld) if(tests) target_compile_definitions(xrpld PUBLIC ENABLE_TESTS) target_compile_definitions( diff --git a/cmake/XrplSanitizers.cmake b/cmake/XrplSanitizers.cmake index 64f1841bfb..893c880374 100644 --- a/cmake/XrplSanitizers.cmake +++ b/cmake/XrplSanitizers.cmake @@ -14,11 +14,9 @@ include_guard(GLOBAL) include(CompilationEnv) -if(NOT DEFINED SANITIZERS) - set(SANITIZERS_ENABLED FALSE) +if(NOT SANITIZERS_ENABLED) return() endif() -set(SANITIZERS_ENABLED TRUE) message(STATUS "=== Configuring Sanitizers ===") message(STATUS " SANITIZERS: ${SANITIZERS}") diff --git a/src/tests/libxrpl/CMakeLists.txt b/src/tests/libxrpl/CMakeLists.txt index 2dae6fccb9..bd56028728 100644 --- a/src/tests/libxrpl/CMakeLists.txt +++ b/src/tests/libxrpl/CMakeLists.txt @@ -13,6 +13,7 @@ add_executable( helpers/TestSink.cpp helpers/TxTest.cpp ) +patch_nix_binary(xrpl_tests) set_target_properties( xrpl_tests PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" From eef8f4a4ff29a76acdc261ab2a309b55ae3cb18e Mon Sep 17 00:00:00 2001 From: Ayaz Salikhov Date: Wed, 24 Jun 2026 18:23:29 +0100 Subject: [PATCH 11/14] chore: Use clang-tidy v22 new features (#7427) --- .clang-tidy | 8 ++- .../scripts/levelization/results/ordering.txt | 1 - include/xrpl/basics/DecayingSample.h | 6 +- include/xrpl/basics/Log.h | 3 +- include/xrpl/basics/TaggedCache.h | 4 +- include/xrpl/basics/TaggedCache.ipp | 4 +- include/xrpl/basics/hardened_hash.h | 2 +- .../xrpl/basics/partitioned_unordered_map.h | 8 +-- include/xrpl/basics/random.h | 1 + include/xrpl/beast/asio/io_latency_probe.h | 4 +- include/xrpl/beast/clock/abstract_clock.h | 8 +-- .../xrpl/beast/clock/basic_seconds_clock.h | 8 +-- .../detail/aged_container_iterator.h | 6 +- .../container/detail/aged_ordered_container.h | 29 ++++---- .../detail/aged_unordered_container.h | 32 ++++----- include/xrpl/beast/core/List.h | 6 +- include/xrpl/beast/core/LockFreeStack.h | 6 +- include/xrpl/beast/hash/uhash.h | 2 +- include/xrpl/beast/rfc2616.h | 2 +- .../beast/unit_test/detail/const_container.h | 10 +-- include/xrpl/beast/unit_test/reporter.h | 14 ++-- include/xrpl/beast/utility/Journal.h | 6 +- include/xrpl/beast/utility/maybe_const.h | 2 +- include/xrpl/beast/utility/rngfill.h | 4 +- include/xrpl/json/json_value.h | 7 +- include/xrpl/protocol/KnownFormats.h | 4 +- include/xrpl/protocol/STBitString.h | 2 +- include/xrpl/protocol/STInteger.h | 2 +- include/xrpl/protocol/STObject.h | 25 +++---- include/xrpl/protocol/TER.h | 4 +- include/xrpl/protocol/Units.h | 2 +- include/xrpl/protocol/XChainAttestations.h | 10 +-- include/xrpl/protocol/digest.h | 4 +- include/xrpl/shamap/FullBelowCache.h | 2 +- src/libxrpl/json/json_valueiterator.cpp | 2 +- src/libxrpl/protocol/XChainAttestations.cpp | 8 +-- src/libxrpl/protocol/tokens.cpp | 8 +-- src/libxrpl/shamap/SHAMapInnerNode.cpp | 2 +- src/libxrpl/tx/invariants/InvariantCheck.cpp | 2 + src/libxrpl/tx/paths/BookStep.cpp | 4 +- src/libxrpl/tx/paths/Flow.cpp | 4 +- .../tx/transactors/system/TicketCreate.cpp | 2 +- src/test/app/LedgerReplay_test.cpp | 4 +- src/test/app/Loan_test.cpp | 4 +- src/test/app/NFTokenDir_test.cpp | 10 +-- src/test/app/OfferMPT_test.cpp | 4 +- src/test/app/Offer_test.cpp | 8 +-- src/test/app/TxQ_test.cpp | 2 +- .../beast/aged_associative_container_test.cpp | 68 +++++++++---------- .../beast/beast_io_latency_probe_test.cpp | 4 +- .../consensus/ByzantineFailureSim_test.cpp | 1 - src/test/consensus/Consensus_test.cpp | 1 - .../DistributedValidatorsSim_test.cpp | 1 - src/test/consensus/ScaleFreeSim_test.cpp | 1 - src/test/csf/BasicNetwork.h | 4 +- src/test/csf/Digraph.h | 6 +- src/test/csf/Scheduler.h | 18 ++--- src/test/csf/SimTime.h | 4 +- src/test/csf/random.h | 4 +- src/test/jtx/TestHelpers.h | 7 +- src/test/nodestore/Timing_test.cpp | 2 +- src/test/server/Server_test.cpp | 2 +- src/test/unit_test/multi_runner.cpp | 4 +- src/test/unit_test/multi_runner.h | 6 +- src/xrpld/app/consensus/RCLConsensus.cpp | 4 ++ src/xrpld/app/consensus/RCLValidations.cpp | 2 + src/xrpld/app/ledger/LedgerHistory.cpp | 4 ++ src/xrpld/app/ledger/detail/BuildLedger.cpp | 2 + src/xrpld/app/ledger/detail/LedgerCleaner.cpp | 2 + src/xrpld/app/ledger/detail/LedgerMaster.cpp | 6 ++ src/xrpld/app/main/Application.cpp | 2 + src/xrpld/app/misc/NetworkOPs.cpp | 2 + src/xrpld/app/misc/detail/Transaction.cpp | 2 +- src/xrpld/app/misc/detail/ValidatorSite.cpp | 2 + src/xrpld/app/rdb/backend/detail/Node.cpp | 10 +-- src/xrpld/consensus/Consensus.h | 30 ++++---- src/xrpld/consensus/ConsensusTypes.h | 8 +-- src/xrpld/consensus/DisputedTx.h | 2 +- src/xrpld/consensus/LedgerTrie.h | 12 ++-- src/xrpld/consensus/Validations.h | 14 ++-- src/xrpld/overlay/Slot.h | 21 +++--- src/xrpld/overlay/Squelch.h | 2 +- src/xrpld/overlay/detail/PeerImp.h | 2 +- src/xrpld/overlay/detail/ZeroCopyStream.h | 6 +- src/xrpld/peerfinder/detail/Checker.h | 8 +-- src/xrpld/peerfinder/detail/Livecache.h | 23 +++---- src/xrpld/peerfinder/detail/Logic.h | 2 +- src/xrpld/rpc/detail/RPCCall.cpp | 2 +- .../handlers/admin/keygen/WalletPropose.cpp | 2 +- src/xrpld/rpc/json_body.h | 2 +- 90 files changed, 315 insertions(+), 294 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index e8e2ca7ac9..35427810a3 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -11,6 +11,7 @@ Checks: "-*, bugprone-copy-constructor-init, bugprone-crtp-constructor-accessibility, bugprone-dangling-handle, + bugprone-derived-method-shadowing-base-method, bugprone-dynamic-static-initializers, bugprone-empty-catch, bugprone-fold-init-type, @@ -21,6 +22,7 @@ Checks: "-*, bugprone-incorrect-roundings, bugprone-infinite-loop, bugprone-integer-division, + bugprone-invalid-enum-default-initialization, bugprone-lambda-function-name, bugprone-macro-parentheses, bugprone-macro-repeated-side-effects, @@ -137,6 +139,7 @@ Checks: "-*, readability-enum-initial-value, readability-identifier-naming, readability-implicit-bool-conversion, + readability-inconsistent-ifelse-braces, readability-make-member-function-const, readability-math-missing-parentheses, readability-misleading-indentation, @@ -145,7 +148,9 @@ Checks: "-*, readability-redundant-declaration, readability-redundant-inline-specifier, readability-redundant-member-init, + readability-redundant-parentheses, readability-redundant-string-init, + readability-redundant-typename, readability-reference-to-constructed-temporary, readability-simplify-boolean-expr, readability-static-definition-in-anonymous-namespace, @@ -153,7 +158,8 @@ Checks: "-*, readability-use-std-min-max " # --- -# bugprone-narrowing-conversions, # this will break a lot of code but we should enable it in the future because it can eliminate a lot of bugs +# bugprone-narrowing-conversions, # This will break a lot of code but we should enable it in the future because it can eliminate a lot of bugs +# misc-override-with-different-visibility, # Will be addressed in a future PR, but for now it generates too many warnings # readability-inconsistent-declaration-parameter-name, # In this codebase this check will break a lot of arg names # readability-static-accessed-through-instance, # this check is probably unnecessary. It makes the code less readable # --- diff --git a/.github/scripts/levelization/results/ordering.txt b/.github/scripts/levelization/results/ordering.txt index 547c1b3539..7b31042158 100644 --- a/.github/scripts/levelization/results/ordering.txt +++ b/.github/scripts/levelization/results/ordering.txt @@ -83,7 +83,6 @@ test.conditions > xrpl.basics test.conditions > xrpl.conditions test.consensus > test.csf test.consensus > test.jtx -test.consensus > test.toplevel test.consensus > test.unit_test test.consensus > xrpl.basics test.consensus > xrpld.app diff --git a/include/xrpl/basics/DecayingSample.h b/include/xrpl/basics/DecayingSample.h index d1861ebc4a..910c8f9e14 100644 --- a/include/xrpl/basics/DecayingSample.h +++ b/include/xrpl/basics/DecayingSample.h @@ -12,8 +12,8 @@ template class DecayingSample { public: - using value_type = typename Clock::duration::rep; - using time_point = typename Clock::time_point; + using value_type = Clock::duration::rep; + using time_point = Clock::time_point; DecayingSample() = delete; @@ -93,7 +93,7 @@ template class DecayWindow { public: - using time_point = typename Clock::time_point; + using time_point = Clock::time_point; explicit DecayWindow(time_point now) : when_(now) { diff --git a/include/xrpl/basics/Log.h b/include/xrpl/basics/Log.h index 6bafbc7c54..0699cdd3d9 100644 --- a/include/xrpl/basics/Log.h +++ b/include/xrpl/basics/Log.h @@ -206,8 +206,7 @@ private: #ifndef JLOG #define JLOG(x) \ if (!(x)) \ - { \ - } \ + ; \ else \ x #endif diff --git a/include/xrpl/basics/TaggedCache.h b/include/xrpl/basics/TaggedCache.h index ecf6071f8d..973fcd828a 100644 --- a/include/xrpl/basics/TaggedCache.h +++ b/include/xrpl/basics/TaggedCache.h @@ -338,7 +338,7 @@ private: sweepHelper( clock_type::time_point const& whenExpire, [[maybe_unused]] clock_type::time_point const& now, - typename KeyValueCacheType::map_type& partition, + KeyValueCacheType::map_type& partition, SweptPointersVector& stuffToSweep, std::atomic& allRemovals, std::scoped_lock const&); @@ -347,7 +347,7 @@ private: sweepHelper( clock_type::time_point const& whenExpire, clock_type::time_point const& now, - typename KeyOnlyCacheType::map_type& partition, + KeyOnlyCacheType::map_type& partition, SweptPointersVector&, std::atomic& allRemovals, std::scoped_lock const&); diff --git a/include/xrpl/basics/TaggedCache.ipp b/include/xrpl/basics/TaggedCache.ipp index 6973ec4ba0..7e812ce4c7 100644 --- a/include/xrpl/basics/TaggedCache.ipp +++ b/include/xrpl/basics/TaggedCache.ipp @@ -735,7 +735,7 @@ TaggedCache& allRemovals, std::scoped_lock const&) @@ -815,7 +815,7 @@ TaggedCache& allRemovals, std::scoped_lock const&) diff --git a/include/xrpl/basics/hardened_hash.h b/include/xrpl/basics/hardened_hash.h index efc77e058b..b8ea1e0f3f 100644 --- a/include/xrpl/basics/hardened_hash.h +++ b/include/xrpl/basics/hardened_hash.h @@ -75,7 +75,7 @@ private: detail::seed_pair seeds_{detail::makeSeedPair<>()}; public: - using result_type = typename HashAlgorithm::result_type; + using result_type = HashAlgorithm::result_type; HardenedHash() = default; diff --git a/include/xrpl/basics/partitioned_unordered_map.h b/include/xrpl/basics/partitioned_unordered_map.h index 3bf64985e5..c51cedf2dd 100644 --- a/include/xrpl/basics/partitioned_unordered_map.h +++ b/include/xrpl/basics/partitioned_unordered_map.h @@ -57,8 +57,8 @@ public: { using iterator_category = std::forward_iterator_tag; partition_map_type* map{nullptr}; - typename partition_map_type::iterator ait{}; - typename map_type::iterator mit; + partition_map_type::iterator ait{}; + map_type::iterator mit; Iterator() = default; @@ -126,8 +126,8 @@ public: using iterator_category = std::forward_iterator_tag; partition_map_type* map{nullptr}; - typename partition_map_type::iterator ait{}; - typename map_type::iterator mit; + partition_map_type::iterator ait{}; + map_type::iterator mit; ConstIterator() = default; diff --git a/include/xrpl/basics/random.h b/include/xrpl/basics/random.h index 17f4a1c213..0b298e12d9 100644 --- a/include/xrpl/basics/random.h +++ b/include/xrpl/basics/random.h @@ -29,6 +29,7 @@ static_assert( namespace detail { // Determines if a type can be called like an Engine +// NOLINTNEXTLINE(readability-redundant-typename): typename required by MSVC template using is_engine = std::is_invocable_r; } // namespace detail diff --git a/include/xrpl/beast/asio/io_latency_probe.h b/include/xrpl/beast/asio/io_latency_probe.h index ce3929a394..5e1b098dcb 100644 --- a/include/xrpl/beast/asio/io_latency_probe.h +++ b/include/xrpl/beast/asio/io_latency_probe.h @@ -18,8 +18,8 @@ template class IOLatencyProbe { private: - using duration = typename Clock::duration; - using time_point = typename Clock::time_point; + using duration = Clock::duration; + using time_point = Clock::time_point; std::recursive_mutex mutex_; std::condition_variable_any cond_; diff --git a/include/xrpl/beast/clock/abstract_clock.h b/include/xrpl/beast/clock/abstract_clock.h index 33d4096d0e..15d785d138 100644 --- a/include/xrpl/beast/clock/abstract_clock.h +++ b/include/xrpl/beast/clock/abstract_clock.h @@ -34,10 +34,10 @@ template class AbstractClock { public: - using rep = typename Clock::rep; - using period = typename Clock::period; - using duration = typename Clock::duration; - using time_point = typename Clock::time_point; + using rep = Clock::rep; + using period = Clock::period; + using duration = Clock::duration; + using time_point = Clock::time_point; using clock_type = Clock; static bool const is_steady = Clock::is_steady; // NOLINT(readability-identifier-naming) diff --git a/include/xrpl/beast/clock/basic_seconds_clock.h b/include/xrpl/beast/clock/basic_seconds_clock.h index 8460dbe26b..5a267e9458 100644 --- a/include/xrpl/beast/clock/basic_seconds_clock.h +++ b/include/xrpl/beast/clock/basic_seconds_clock.h @@ -20,10 +20,10 @@ public: explicit BasicSecondsClock() = default; - using rep = typename Clock::rep; - using period = typename Clock::period; - using duration = typename Clock::duration; - using time_point = typename Clock::time_point; + using rep = Clock::rep; + using period = Clock::period; + using duration = Clock::duration; + using time_point = Clock::time_point; static bool const is_steady = // NOLINT(readability-identifier-naming) Clock::is_steady; diff --git a/include/xrpl/beast/container/detail/aged_container_iterator.h b/include/xrpl/beast/container/detail/aged_container_iterator.h index 8d44646cd4..02fb3927dd 100644 --- a/include/xrpl/beast/container/detail/aged_container_iterator.h +++ b/include/xrpl/beast/container/detail/aged_container_iterator.h @@ -16,15 +16,15 @@ template class AgedContainerIterator { public: - using iterator_category = typename std::iterator_traits::iterator_category; + using iterator_category = std::iterator_traits::iterator_category; using value_type = std::conditional_t< IsConst, typename Iterator::value_type::Stashed::value_type const, typename Iterator::value_type::Stashed::value_type>; - using difference_type = typename std::iterator_traits::difference_type; + using difference_type = std::iterator_traits::difference_type; using pointer = value_type*; using reference = value_type&; - using time_point = typename Iterator::value_type::Stashed::time_point; + using time_point = Iterator::value_type::Stashed::time_point; AgedContainerIterator() = default; diff --git a/include/xrpl/beast/container/detail/aged_ordered_container.h b/include/xrpl/beast/container/detail/aged_ordered_container.h index ad368f2754..4cb2246a22 100644 --- a/include/xrpl/beast/container/detail/aged_ordered_container.h +++ b/include/xrpl/beast/container/detail/aged_ordered_container.h @@ -62,8 +62,8 @@ class AgedOrderedContainer { public: using clock_type = AbstractClock; - using time_point = typename clock_type::time_point; - using duration = typename clock_type::duration; + using time_point = clock_type::time_point; + using duration = clock_type::duration; using key_type = Key; using mapped_type = T; using value_type = std::conditional_t, Key>; @@ -94,8 +94,8 @@ private: { explicit Stashed() = default; - using value_type = typename AgedOrderedContainer::value_type; - using time_point = typename AgedOrderedContainer::time_point; + using value_type = AgedOrderedContainer::value_type; + using time_point = AgedOrderedContainer::time_point; }; Element(time_point const& when, value_type const& value) : value(value), when(when) @@ -192,8 +192,8 @@ private: } }; - using list_type = typename boost::intrusive:: - make_list>::type; + using list_type = + boost::intrusive::make_list>::type; using cont_type = std::conditional_t< IsMulti, @@ -206,8 +206,7 @@ private: boost::intrusive::constant_time_size, boost::intrusive::compare>::type>; - using ElementAllocator = - typename std::allocator_traits::template rebind_alloc; + using ElementAllocator = std::allocator_traits::template rebind_alloc; using ElementAllocatorTraits = std::allocator_traits; @@ -373,8 +372,8 @@ public: using allocator_type = Allocator; using reference = value_type&; using const_reference = value_type const&; - using pointer = typename std::allocator_traits::pointer; - using const_pointer = typename std::allocator_traits::const_pointer; + using pointer = std::allocator_traits::pointer; + using const_pointer = std::allocator_traits::const_pointer; // A set iterator (IsMap==false) is always const // because the elements of a set are immutable. @@ -617,7 +616,7 @@ public: bool MaybeMulti = IsMulti, bool MaybeMap = IsMap, class = std::enable_if_t> - typename std::conditional::type const& + std::conditional::type const& at(K const& k) const; template < @@ -1146,7 +1145,7 @@ private: void touch( beast::detail::AgedContainerIterator pos, - typename clock_type::time_point const& now); + clock_type::time_point const& now); template < bool MaybePropagate = std::allocator_traits::propagate_on_container_swap::value> @@ -1393,7 +1392,7 @@ AgedOrderedContainer::at(K co template template -typename std::conditional::type const& +std::conditional::type const& AgedOrderedContainer::at(K const& k) const { auto const iter(cont_.find(k, std::cref(config_.keyCompare()))); @@ -1732,7 +1731,7 @@ AgedOrderedContainer::operato cend(), other.cbegin(), other.cend(), - [&eq, &other](value_type const& lhs, typename Other::value_type const& rhs) { + [&eq, &other](value_type const& lhs, Other::value_type const& rhs) { return eq(extract(lhs), other.extract(rhs)); }); } @@ -1744,7 +1743,7 @@ template void AgedOrderedContainer::touch( beast::detail::AgedContainerIterator pos, - typename clock_type::time_point const& now) + clock_type::time_point const& now) { auto& e(*pos.iterator()); e.when = now; diff --git a/include/xrpl/beast/container/detail/aged_unordered_container.h b/include/xrpl/beast/container/detail/aged_unordered_container.h index 7162c237d6..3bad12d9e5 100644 --- a/include/xrpl/beast/container/detail/aged_unordered_container.h +++ b/include/xrpl/beast/container/detail/aged_unordered_container.h @@ -67,8 +67,8 @@ class AgedUnorderedContainer { public: using clock_type = AbstractClock; - using time_point = typename clock_type::time_point; - using duration = typename clock_type::duration; + using time_point = clock_type::time_point; + using duration = clock_type::duration; using key_type = Key; using mapped_type = T; using value_type = std::conditional_t, Key>; @@ -99,8 +99,8 @@ private: { explicit Stashed() = default; - using value_type = typename AgedUnorderedContainer::value_type; - using time_point = typename AgedUnorderedContainer::time_point; + using value_type = AgedUnorderedContainer::value_type; + using time_point = AgedUnorderedContainer::time_point; }; Element(time_point const& when, value_type const& value) : value(value), when(when) @@ -201,8 +201,8 @@ private: } }; - using list_type = typename boost::intrusive:: - make_list>::type; + using list_type = + boost::intrusive::make_list>::type; using cont_type = std::conditional_t< IsMulti, @@ -219,16 +219,14 @@ private: boost::intrusive::equal, boost::intrusive::cache_begin>::type>; - using bucket_type = typename cont_type::bucket_type; - using bucket_traits = typename cont_type::bucket_traits; + using bucket_type = cont_type::bucket_type; + using bucket_traits = cont_type::bucket_traits; - using ElementAllocator = - typename std::allocator_traits::template rebind_alloc; + using ElementAllocator = std::allocator_traits::template rebind_alloc; using ElementAllocatorTraits = std::allocator_traits; - using BucketAllocator = - typename std::allocator_traits::template rebind_alloc; + using BucketAllocator = std::allocator_traits::template rebind_alloc; using BucketAllocatorTraits = std::allocator_traits; @@ -542,8 +540,8 @@ public: using allocator_type = Allocator; using reference = value_type&; using const_reference = value_type const&; - using pointer = typename std::allocator_traits::pointer; - using const_pointer = typename std::allocator_traits::const_pointer; + using pointer = std::allocator_traits::pointer; + using const_pointer = std::allocator_traits::const_pointer; // A set iterator (IsMap==false) is always const // because the elements of a set are immutable. @@ -850,7 +848,7 @@ public: bool MaybeMulti = IsMulti, bool MaybeMap = IsMap, class = std::enable_if_t> - typename std::conditional::type const& + std::conditional::type const& at(K const& k) const; template < @@ -1414,7 +1412,7 @@ private: void touch( beast::detail::AgedContainerIterator pos, - typename clock_type::time_point const& now) + clock_type::time_point const& now) { auto& e(*pos.iterator()); e.when = now; @@ -2111,7 +2109,7 @@ template < class KeyEqual, class Allocator> template -typename std::conditional::type const& +std::conditional::type const& AgedUnorderedContainer::at( K const& k) const { diff --git a/include/xrpl/beast/core/List.h b/include/xrpl/beast/core/List.h index 946126a004..1c3827ae1c 100644 --- a/include/xrpl/beast/core/List.h +++ b/include/xrpl/beast/core/List.h @@ -24,7 +24,7 @@ struct CopyConst { explicit CopyConst() = default; - using type = typename std::remove_const::type const; + using type = std::remove_const::type const; }; /** @} */ @@ -56,7 +56,7 @@ class ListIterator { public: using iterator_category = std::bidirectional_iterator_tag; - using value_type = typename beast::detail::CopyConst::type; + using value_type = beast::detail::CopyConst::type; using difference_type = std::ptrdiff_t; using pointer = value_type*; using reference = value_type&; @@ -259,7 +259,7 @@ template class List { public: - using Node = typename detail::ListNode; + using Node = detail::ListNode; using value_type = T; using pointer = value_type*; diff --git a/include/xrpl/beast/core/LockFreeStack.h b/include/xrpl/beast/core/LockFreeStack.h index 6b8f686246..d4ad45cf5c 100644 --- a/include/xrpl/beast/core/LockFreeStack.h +++ b/include/xrpl/beast/core/LockFreeStack.h @@ -12,13 +12,13 @@ template class LockFreeStackIterator { protected: - using Node = typename Container::Node; + using Node = Container::Node; using NodePtr = std::conditional_t; public: using iterator_category = std::forward_iterator_tag; - using value_type = typename Container::value_type; - using difference_type = typename Container::difference_type; + using value_type = Container::value_type; + using difference_type = Container::difference_type; using pointer = std::conditional_t; using reference = std:: diff --git a/include/xrpl/beast/hash/uhash.h b/include/xrpl/beast/hash/uhash.h index 97461f67c7..9ffd5924f7 100644 --- a/include/xrpl/beast/hash/uhash.h +++ b/include/xrpl/beast/hash/uhash.h @@ -11,7 +11,7 @@ struct Uhash { Uhash() = default; - using result_type = typename Hasher::result_type; + using result_type = Hasher::result_type; template result_type diff --git a/include/xrpl/beast/rfc2616.h b/include/xrpl/beast/rfc2616.h index cf80bd26c0..e810733210 100644 --- a/include/xrpl/beast/rfc2616.h +++ b/include/xrpl/beast/rfc2616.h @@ -102,7 +102,7 @@ Result split(FwdIt first, FwdIt last, Char delim) { using namespace detail; - using string = typename Result::value_type; + using string = Result::value_type; Result result; diff --git a/include/xrpl/beast/unit_test/detail/const_container.h b/include/xrpl/beast/unit_test/detail/const_container.h index c171771e45..6826bf4258 100644 --- a/include/xrpl/beast/unit_test/detail/const_container.h +++ b/include/xrpl/beast/unit_test/detail/const_container.h @@ -32,11 +32,11 @@ protected: } public: - using value_type = typename cont_type::value_type; - using size_type = typename cont_type::size_type; - using difference_type = typename cont_type::difference_type; - using iterator = typename cont_type::const_iterator; - using const_iterator = typename cont_type::const_iterator; + using value_type = cont_type::value_type; + using size_type = cont_type::size_type; + using difference_type = cont_type::difference_type; + using iterator = cont_type::const_iterator; + using const_iterator = cont_type::const_iterator; /** Returns `true` if the container is empty. */ [[nodiscard]] bool diff --git a/include/xrpl/beast/unit_test/reporter.h b/include/xrpl/beast/unit_test/reporter.h index 1fdbb451a6..ff990dece5 100644 --- a/include/xrpl/beast/unit_test/reporter.h +++ b/include/xrpl/beast/unit_test/reporter.h @@ -48,7 +48,7 @@ private: std::size_t cases = 0; std::size_t total = 0; std::size_t failed = 0; - typename clock_type::time_point start = clock_type::now(); + clock_type::time_point start = clock_type::now(); explicit SuiteResults(std::string name = "") : name(std::move(name)) { @@ -60,7 +60,7 @@ private: struct Results { - using run_time = std::pair; + using run_time = std::pair; static constexpr auto kMaxTop = 10; @@ -69,7 +69,7 @@ private: std::size_t total = 0; std::size_t failed = 0; std::vector top; - typename clock_type::time_point start = clock_type::now(); + clock_type::time_point start = clock_type::now(); void add(SuiteResults const& r); @@ -91,7 +91,7 @@ public: private: static std::string - fmtdur(typename clock_type::duration const& d); + fmtdur(clock_type::duration const& d); void onSuiteBegin(SuiteInfo const& info) override; @@ -141,9 +141,7 @@ Reporter::Results::add(SuiteResults const& r) top.begin(), top.end(), elapsed, - [](run_time const& t1, typename clock_type::duration const& t2) { - return t1.second > t2; - }); + [](run_time const& t1, clock_type::duration const& t2) { return t1.second > t2; }); if (iter != top.end()) { if (top.size() == kMaxTop) @@ -181,7 +179,7 @@ Reporter::~Reporter() template std::string -Reporter::fmtdur(typename clock_type::duration const& d) +Reporter::fmtdur(clock_type::duration const& d) { using namespace std::chrono; auto const ms = duration_cast(d); diff --git a/include/xrpl/beast/utility/Journal.h b/include/xrpl/beast/utility/Journal.h index 1a0c148d1f..1262a64179 100644 --- a/include/xrpl/beast/utility/Journal.h +++ b/include/xrpl/beast/utility/Journal.h @@ -411,9 +411,9 @@ class BasicLogstream : public std::basic_ostream { using char_type = CharT; using traits_type = Traits; - using int_type = typename traits_type::int_type; - using pos_type = typename traits_type::pos_type; - using off_type = typename traits_type::off_type; + using int_type = traits_type::int_type; + using pos_type = traits_type::pos_type; + using off_type = traits_type::off_type; detail::LogStreamBuf buf_; diff --git a/include/xrpl/beast/utility/maybe_const.h b/include/xrpl/beast/utility/maybe_const.h index 40904471be..10b2eaf7f6 100644 --- a/include/xrpl/beast/utility/maybe_const.h +++ b/include/xrpl/beast/utility/maybe_const.h @@ -15,6 +15,6 @@ struct MaybeConst /** Alias for omitting `typename`. */ template -using maybe_const_t = typename MaybeConst::type; +using maybe_const_t = MaybeConst::type; } // namespace beast diff --git a/include/xrpl/beast/utility/rngfill.h b/include/xrpl/beast/utility/rngfill.h index 1614a594c5..2ea84a7a3d 100644 --- a/include/xrpl/beast/utility/rngfill.h +++ b/include/xrpl/beast/utility/rngfill.h @@ -13,7 +13,7 @@ template void rngfill(void* const buffer, std::size_t const bytes, Generator& g) { - using result_type = typename Generator::result_type; + using result_type = Generator::result_type; constexpr std::size_t kResultSize = sizeof(result_type); std::uint8_t* const bufferStart = static_cast(buffer); @@ -42,7 +42,7 @@ template < void rngfill(std::array& a, Generator& g) { - using result_type = typename Generator::result_type; + using result_type = Generator::result_type; auto i = N / sizeof(result_type); result_type* p = reinterpret_cast(a.data()); while (i--) diff --git a/include/xrpl/json/json_value.h b/include/xrpl/json/json_value.h index e9dcb8bcbe..f786c6a9dc 100644 --- a/include/xrpl/json/json_value.h +++ b/include/xrpl/json/json_value.h @@ -566,6 +566,7 @@ public: using SelfType = ValueConstIterator; ValueConstIterator() = default; + ValueConstIterator(ValueConstIterator const& other) = default; private: /*! \internal Use by Value to create an iterator. @@ -574,12 +575,12 @@ private: public: SelfType& - operator=(ValueIteratorBase const& other); + operator=(SelfType const& other); SelfType operator++(int) { - SelfType temp(*this); + SelfType const temp(*this); ++*this; return temp; } @@ -587,7 +588,7 @@ public: SelfType operator--(int) { - SelfType temp(*this); + SelfType const temp(*this); --*this; return temp; } diff --git a/include/xrpl/protocol/KnownFormats.h b/include/xrpl/protocol/KnownFormats.h index 9aa914ba97..6e21d4bc3a 100644 --- a/include/xrpl/protocol/KnownFormats.h +++ b/include/xrpl/protocol/KnownFormats.h @@ -118,13 +118,13 @@ public: } // begin() and end() are provided for testing purposes. - [[nodiscard]] typename std::forward_list::const_iterator + [[nodiscard]] std::forward_list::const_iterator begin() const { return formats_.begin(); } - [[nodiscard]] typename std::forward_list::const_iterator + [[nodiscard]] std::forward_list::const_iterator end() const { return formats_.end(); diff --git a/include/xrpl/protocol/STBitString.h b/include/xrpl/protocol/STBitString.h index 87c8cd4f45..0267eac22d 100644 --- a/include/xrpl/protocol/STBitString.h +++ b/include/xrpl/protocol/STBitString.h @@ -163,7 +163,7 @@ STBitString::setValue(BaseUInt const& v) } template -typename STBitString::value_type const& +STBitString::value_type const& STBitString::value() const { return value_; diff --git a/include/xrpl/protocol/STInteger.h b/include/xrpl/protocol/STInteger.h index 4e3c9a8923..52e0f7a365 100644 --- a/include/xrpl/protocol/STInteger.h +++ b/include/xrpl/protocol/STInteger.h @@ -120,7 +120,7 @@ STInteger::operator=(value_type const& v) } template -inline typename STInteger::value_type +inline STInteger::value_type STInteger::value() const noexcept { return value_; diff --git a/include/xrpl/protocol/STObject.h b/include/xrpl/protocol/STObject.h index c635e8ce22..e65cc79c78 100644 --- a/include/xrpl/protocol/STObject.h +++ b/include/xrpl/protocol/STObject.h @@ -243,7 +243,7 @@ public: @throws STObject::FieldErr if the field is not present. */ template - typename T::value_type + T::value_type operator[](TypedField const& f) const; /** Get the value of a field as a std::optional @@ -290,7 +290,7 @@ public: @throws STObject::FieldErr if the field is not present. */ template - [[nodiscard]] typename T::value_type + [[nodiscard]] T::value_type at(TypedField const& f) const; /** Get the value of a field as std::optional @@ -478,7 +478,7 @@ template class STObject::Proxy { public: - using value_type = typename T::value_type; + using value_type = T::value_type; [[nodiscard]] value_type value() const; @@ -513,13 +513,10 @@ protected: template concept IsArithmeticNumber = std::is_arithmetic_v || std::is_same_v || std::is_same_v; -template < - typename U, - typename Value = typename U::value_type, - typename Unit = typename U::unit_type> +template concept IsArithmeticValueUnit = std::is_same_v> && IsArithmeticNumber && std::is_class_v; -template +template concept IsArithmeticST = !IsArithmeticValueUnit && IsArithmeticNumber; template concept IsArithmetic = IsArithmeticNumber || IsArithmeticST || IsArithmeticValueUnit; @@ -534,7 +531,7 @@ template class STObject::ValueProxy : public Proxy { private: - using value_type = typename T::value_type; + using value_type = T::value_type; public: ValueProxy(ValueProxy const&) = default; @@ -576,7 +573,7 @@ template class STObject::OptionalProxy : public Proxy { private: - using value_type = typename T::value_type; + using value_type = T::value_type; using optional_type = std::optional>; @@ -840,7 +837,7 @@ operator typename STObject::OptionalProxy::optional_type() const } template -typename STObject::OptionalProxy::optional_type +STObject::OptionalProxy::optional_type STObject::OptionalProxy::operator~() const { return optionalValue(); @@ -933,7 +930,7 @@ STObject::OptionalProxy::optionalValue() const -> optional_type } template -typename STObject::OptionalProxy::value_type +STObject::OptionalProxy::value_type STObject::OptionalProxy::valueOr(value_type val) const { return engaged() ? this->value() : val; @@ -1040,7 +1037,7 @@ STObject::getPIndex(int offset) } template -typename T::value_type +T::value_type STObject::operator[](TypedField const& f) const { return at(f); @@ -1068,7 +1065,7 @@ STObject::operator[](OptionaledField const& of) -> OptionalProxy } template -[[nodiscard]] typename T::value_type +[[nodiscard]] T::value_type STObject::at(TypedField const& f) const { auto const b = peekAtPField(f); diff --git a/include/xrpl/protocol/TER.h b/include/xrpl/protocol/TER.h index c89610f354..072bd4778f 100644 --- a/include/xrpl/protocol/TER.h +++ b/include/xrpl/protocol/TER.h @@ -657,13 +657,13 @@ inline bool isTesSuccess(TER x) noexcept { // Makes use of TERSubset::operator bool() - return !(x); + return !x; } inline bool isTecClaim(TER x) noexcept { - return ((x) >= tecCLAIM); + return (x >= tecCLAIM); } std::unordered_map> const& diff --git a/include/xrpl/protocol/Units.h b/include/xrpl/protocol/Units.h index 7fedc05a0d..39f745e84e 100644 --- a/include/xrpl/protocol/Units.h +++ b/include/xrpl/protocol/Units.h @@ -391,7 +391,7 @@ mulDivU(Source1 value, Dest mul, Source2 div) return std::nullopt; } - using desttype = typename Dest::value_type; + using desttype = Dest::value_type; constexpr auto kMax = std::numeric_limits::max(); // Shortcuts, since these happen a lot in the real world diff --git a/include/xrpl/protocol/XChainAttestations.h b/include/xrpl/protocol/XChainAttestations.h index 457af727a2..1aec5fe549 100644 --- a/include/xrpl/protocol/XChainAttestations.h +++ b/include/xrpl/protocol/XChainAttestations.h @@ -379,16 +379,16 @@ public: [[nodiscard]] STArray toSTArray() const; - [[nodiscard]] typename AttCollection::const_iterator + [[nodiscard]] AttCollection::const_iterator begin() const; - [[nodiscard]] typename AttCollection::const_iterator + [[nodiscard]] AttCollection::const_iterator end() const; - typename AttCollection::iterator + AttCollection::iterator begin(); - typename AttCollection::iterator + AttCollection::iterator end(); template @@ -419,7 +419,7 @@ operator==( } template -inline typename XChainAttestationsBase::AttCollection const& +inline XChainAttestationsBase::AttCollection const& XChainAttestationsBase::attestations() const { return attestations_; diff --git a/include/xrpl/protocol/digest.h b/include/xrpl/protocol/digest.h index 50bf2735fb..721ce60767 100644 --- a/include/xrpl/protocol/digest.h +++ b/include/xrpl/protocol/digest.h @@ -206,7 +206,7 @@ sha512Half(Args const&... args) sha512_half_hasher h; using beast::hash_append; hash_append(h, args...); - return static_cast(h); + return static_cast(h); } /** Returns the SHA512-Half of a series of objects. @@ -222,7 +222,7 @@ sha512HalfS(Args const&... args) sha512_half_hasher_s h; using beast::hash_append; hash_append(h, args...); - return static_cast(h); + return static_cast(h); } } // namespace xrpl diff --git a/include/xrpl/shamap/FullBelowCache.h b/include/xrpl/shamap/FullBelowCache.h index 07290dfbd1..e9fd04ac58 100644 --- a/include/xrpl/shamap/FullBelowCache.h +++ b/include/xrpl/shamap/FullBelowCache.h @@ -25,7 +25,7 @@ public: static constexpr auto kDefaultCacheTargetSize = 0; using key_type = uint256; - using clock_type = typename CacheType::clock_type; + using clock_type = CacheType::clock_type; /** Construct the cache. diff --git a/src/libxrpl/json/json_valueiterator.cpp b/src/libxrpl/json/json_valueiterator.cpp index 5a3a5ffcdb..bb49902f70 100644 --- a/src/libxrpl/json/json_valueiterator.cpp +++ b/src/libxrpl/json/json_valueiterator.cpp @@ -132,7 +132,7 @@ ValueConstIterator::ValueConstIterator(Value::ObjectValues::iterator const& curr } ValueConstIterator& -ValueConstIterator::operator=(ValueIteratorBase const& other) +ValueConstIterator::operator=(SelfType const& other) { copy(other); return *this; diff --git a/src/libxrpl/protocol/XChainAttestations.cpp b/src/libxrpl/protocol/XChainAttestations.cpp index 805d08c097..792fe5da9d 100644 --- a/src/libxrpl/protocol/XChainAttestations.cpp +++ b/src/libxrpl/protocol/XChainAttestations.cpp @@ -628,28 +628,28 @@ XChainAttestationsBase::XChainAttestationsBase( } template -typename XChainAttestationsBase::AttCollection::const_iterator +XChainAttestationsBase::AttCollection::const_iterator XChainAttestationsBase::begin() const { return attestations_.begin(); } template -typename XChainAttestationsBase::AttCollection::const_iterator +XChainAttestationsBase::AttCollection::const_iterator XChainAttestationsBase::end() const { return attestations_.end(); } template -typename XChainAttestationsBase::AttCollection::iterator +XChainAttestationsBase::AttCollection::iterator XChainAttestationsBase::begin() { return attestations_.begin(); } template -typename XChainAttestationsBase::AttCollection::iterator +XChainAttestationsBase::AttCollection::iterator XChainAttestationsBase::end() { return attestations_.end(); diff --git a/src/libxrpl/protocol/tokens.cpp b/src/libxrpl/protocol/tokens.cpp index fcd822a747..d04ceaa3a6 100644 --- a/src/libxrpl/protocol/tokens.cpp +++ b/src/libxrpl/protocol/tokens.cpp @@ -135,16 +135,16 @@ static constexpr std::array const kAlphabetReverse = []() { }(); template -static typename Hasher::result_type +static Hasher::result_type digest(void const* data, std::size_t size) noexcept { Hasher h; h(data, size); - return static_cast(h); + return static_cast(h); } template > -static typename Hasher::result_type +static Hasher::result_type digest(std::array const& v) { return digest(v.data(), v.size()); @@ -152,7 +152,7 @@ digest(std::array const& v) // Computes a double digest (e.g. digest of the digest) template -static typename Hasher::result_type +static Hasher::result_type digest2(Args const&... args) { return digest(digest(args...)); diff --git a/src/libxrpl/shamap/SHAMapInnerNode.cpp b/src/libxrpl/shamap/SHAMapInnerNode.cpp index ee6ebf7f3f..74a0e4515f 100644 --- a/src/libxrpl/shamap/SHAMapInnerNode.cpp +++ b/src/libxrpl/shamap/SHAMapInnerNode.cpp @@ -200,7 +200,7 @@ SHAMapInnerNode::updateHash() using beast::hash_append; hash_append(h, HashPrefix::InnerNode); iterChildren([&](SHAMapHash const& hh) { hash_append(h, hh); }); - nh = static_cast(h); + nh = static_cast(h); } hash_ = SHAMapHash{nh}; } diff --git a/src/libxrpl/tx/invariants/InvariantCheck.cpp b/src/libxrpl/tx/invariants/InvariantCheck.cpp index b4a533905c..e29a9fe661 100644 --- a/src/libxrpl/tx/invariants/InvariantCheck.cpp +++ b/src/libxrpl/tx/invariants/InvariantCheck.cpp @@ -407,8 +407,10 @@ AccountRootsNotDeleted::finalize( "succeeded without deleting an account"; } else + { JLOG(j.fatal()) << "Invariant failed: account deletion " "succeeded but deleted multiple accounts!"; + } return false; } diff --git a/src/libxrpl/tx/paths/BookStep.cpp b/src/libxrpl/tx/paths/BookStep.cpp index 4b045521d2..448172872a 100644 --- a/src/libxrpl/tx/paths/BookStep.cpp +++ b/src/libxrpl/tx/paths/BookStep.cpp @@ -1477,8 +1477,8 @@ bookStepEqual(Step const& step, xrpl::Book const& book) { return std::visit( [&](TIn const&, TOut const&) { - using TIn_ = typename TIn::amount_type; - using TOut_ = typename TOut::amount_type; + using TIn_ = TIn::amount_type; + using TOut_ = TOut::amount_type; if constexpr (ValidTaker) { diff --git a/src/libxrpl/tx/paths/Flow.cpp b/src/libxrpl/tx/paths/Flow.cpp index 7be1f9f633..80e05f058c 100644 --- a/src/libxrpl/tx/paths/Flow.cpp +++ b/src/libxrpl/tx/paths/Flow.cpp @@ -125,8 +125,8 @@ flow( // amount types. return std::visit( [&, &strands = strands](TIn const&, TOut const&) { - using TIn_ = typename TIn::amount_type; - using TOut_ = typename TOut::amount_type; + using TIn_ = TIn::amount_type; + using TOut_ = TOut::amount_type; return finishFlow( sb, srcAsset, diff --git a/src/libxrpl/tx/transactors/system/TicketCreate.cpp b/src/libxrpl/tx/transactors/system/TicketCreate.cpp index 5be00fe76c..be24b6326a 100644 --- a/src/libxrpl/tx/transactors/system/TicketCreate.cpp +++ b/src/libxrpl/tx/transactors/system/TicketCreate.cpp @@ -120,7 +120,7 @@ TicketCreate::doApply() } // Update the record of the number of Tickets this account owns. - std::uint32_t const oldTicketCount = (*(sleAccountRoot))[~sfTicketCount].valueOr(0u); + std::uint32_t const oldTicketCount = (*sleAccountRoot)[~sfTicketCount].valueOr(0u); sleAccountRoot->setFieldU32(sfTicketCount, oldTicketCount + ticketCount); diff --git a/src/test/app/LedgerReplay_test.cpp b/src/test/app/LedgerReplay_test.cpp index 810d93e6e1..2422db05de 100644 --- a/src/test/app/LedgerReplay_test.cpp +++ b/src/test/app/LedgerReplay_test.cpp @@ -1077,10 +1077,10 @@ struct LedgerReplayer_test : public beast::unit_test::Suite { Config c; - std::string const toLoad = (R"xrpldConfig( + std::string const toLoad = R"xrpldConfig( [ledger_replay] 0 -)xrpldConfig"); +)xrpldConfig"; c.loadFromString(toLoad); BEAST_EXPECT(c.ledgerReplay == false); } diff --git a/src/test/app/Loan_test.cpp b/src/test/app/Loan_test.cpp index dbb0033368..2d70efd9b2 100644 --- a/src/test/app/Loan_test.cpp +++ b/src/test/app/Loan_test.cpp @@ -3006,9 +3006,9 @@ protected: } if (mptTest) - (mptTest)(env, brokers[0], mptt); + mptTest(env, brokers[0], mptt); if (iouTest) - (iouTest)(env, brokers[1]); + iouTest(env, brokers[1]); }; testCase( diff --git a/src/test/app/NFTokenDir_test.cpp b/src/test/app/NFTokenDir_test.cpp index 117f2bc816..e24a524b81 100644 --- a/src/test/app/NFTokenDir_test.cpp +++ b/src/test/app/NFTokenDir_test.cpp @@ -143,7 +143,7 @@ class NFTokenDir_test : public beast::unit_test::Suite for (uint256 const& nftID : nftIDs) { offers.emplace_back(keylet::nftoffer(issuer, env.seq(issuer)).key); - env(token::createOffer(issuer, nftID, XRP(0)), Txflags((tfSellNFToken))); + env(token::createOffer(issuer, nftID, XRP(0)), Txflags(tfSellNFToken)); env.close(); } @@ -217,7 +217,7 @@ class NFTokenDir_test : public beast::unit_test::Suite offers.emplace_back(keylet::nftoffer(account, env.seq(account)).key); env(token::createOffer(account, nftID, XRP(0)), token::Destination(buyer), - Txflags((tfSellNFToken))); + Txflags(tfSellNFToken)); } env.close(); @@ -421,7 +421,7 @@ class NFTokenDir_test : public beast::unit_test::Suite offers.emplace_back(keylet::nftoffer(account, env.seq(account)).key); env(token::createOffer(account, nftID, XRP(0)), token::Destination(buyer), - Txflags((tfSellNFToken))); + Txflags(tfSellNFToken)); } env.close(); @@ -651,7 +651,7 @@ class NFTokenDir_test : public beast::unit_test::Suite offers.emplace_back(keylet::nftoffer(account, env.seq(account)).key); env(token::createOffer(account, nftID, XRP(0)), token::Destination(buyer), - Txflags((tfSellNFToken))); + Txflags(tfSellNFToken)); } env.close(); @@ -823,7 +823,7 @@ class NFTokenDir_test : public beast::unit_test::Suite offers[i].emplace_back(keylet::nftoffer(account, env.seq(account)).key); env(token::createOffer(account, nftID, XRP(0)), token::Destination(buyer), - Txflags((tfSellNFToken))); + Txflags(tfSellNFToken)); } } env.close(); diff --git a/src/test/app/OfferMPT_test.cpp b/src/test/app/OfferMPT_test.cpp index ed0b2ffbe3..ac50924ac2 100644 --- a/src/test/app/OfferMPT_test.cpp +++ b/src/test/app/OfferMPT_test.cpp @@ -3431,7 +3431,7 @@ public: auto const gw = Account("gateway"); auto const fee = env.current()->fees().base; - env.fund(reserve(env, 2) + drops(9999640) + (fee), ann); + env.fund(reserve(env, 2) + drops(9999640) + fee, ann); env.fund(reserve(env, 2) + (fee * 4), gw); env.close(); @@ -3467,7 +3467,7 @@ public: auto const bob = Account("bob"); auto const fee = env.current()->fees().base; - env.fund(reserve(env, 2) + drops(400'000'000'000) + (fee), alice, bob); + env.fund(reserve(env, 2) + drops(400'000'000'000) + fee, alice, bob); env.fund(reserve(env, 2) + (fee * 4), gw); env.close(); diff --git a/src/test/app/Offer_test.cpp b/src/test/app/Offer_test.cpp index ea8b0a7c0e..1a2f0b2b12 100644 --- a/src/test/app/Offer_test.cpp +++ b/src/test/app/Offer_test.cpp @@ -3621,7 +3621,7 @@ public: auto const btc = gw["BTC"]; auto const fee = env.current()->fees().base; - env.fund(reserve(env, 2) + drops(9999640) + (fee), ann); + env.fund(reserve(env, 2) + drops(9999640) + fee, ann); env.fund(reserve(env, 2) + (fee * 4), gw); env.close(); @@ -3659,7 +3659,7 @@ public: auto const cny = gw["CNY"]; auto const fee = env.current()->fees().base; - env.fund(reserve(env, 2) + drops(400000000000) + (fee), alice, bob); + env.fund(reserve(env, 2) + drops(400000000000) + fee, alice, bob); env.fund(reserve(env, 2) + (fee * 4), gw); env.close(); @@ -3706,7 +3706,7 @@ public: auto const jpy = gw["JPY"]; auto const fee = env.current()->fees().base; - env.fund(reserve(env, 2) + drops(400000000000) + (fee), alice, bob); + env.fund(reserve(env, 2) + drops(400000000000) + fee, alice, bob); env.fund(reserve(env, 2) + (fee * 4), gw); env.close(); @@ -3759,7 +3759,7 @@ public: auto const jpy = gw2["JPY"]; auto const fee = env.current()->fees().base; - env.fund(reserve(env, 2) + drops(400000000000) + (fee), alice, bob); + env.fund(reserve(env, 2) + drops(400000000000) + fee, alice, bob); env.fund(reserve(env, 2) + (fee * 4), gw1, gw2); env.close(); diff --git a/src/test/app/TxQ_test.cpp b/src/test/app/TxQ_test.cpp index 0ae6b4d80a..97cb035578 100644 --- a/src/test/app/TxQ_test.cpp +++ b/src/test/app/TxQ_test.cpp @@ -1176,7 +1176,7 @@ public: // bankrupt Alice. Fails, because an account can't have // more than the minimum reserve in flight before the // last queued transaction - aliceFee = env.le(alice)->getFieldAmount(sfBalance).xrp().drops() - (62); + aliceFee = env.le(alice)->getFieldAmount(sfBalance).xrp().drops() - 62; env(noop(alice), Seq(aliceSeq), Fee(aliceFee), Ter(telCAN_NOT_QUEUE_BALANCE)); checkMetrics(*this, env, 4, 10, 6, 5); diff --git a/src/test/beast/aged_associative_container_test.cpp b/src/test/beast/aged_associative_container_test.cpp index d7f74aaa7d..2ac5fc5a33 100644 --- a/src/test/beast/aged_associative_container_test.cpp +++ b/src/test/beast/aged_associative_container_test.cpp @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -232,10 +233,10 @@ public: { public: using T = void; - using Value = typename Base::Key; + using Value = Base::Key; using Values = std::vector; - static typename Base::Key const& + static Base::Key const& extract(Value const& value) { return value; // NOLINT(bugprone-return-const-ref-from-parameter) @@ -271,7 +272,7 @@ public: using Value = std::pair; using Values = std::vector; - static typename Base::Key const& + static Base::Key const& extract(Value const& value) { return value.first; @@ -387,7 +388,7 @@ public: struct EqualValue { bool - operator()(typename Traits::Value const& lhs, typename Traits::Value const& rhs) + operator()(Traits::Value const& lhs, Traits::Value const& rhs) { return Traits::extract(lhs) == Traits::extract(rhs); } @@ -647,7 +648,7 @@ AgedAssociativeContainerTestBase::checkUnorderedContentsRefRef(C&& c, Values con using Cont = std::remove_reference_t; using Traits = TestTraits; - using size_type = typename Cont::size_type; + using size_type = Cont::size_type; auto const hash(c.hashFunction()); auto const keyEq(c.keyEq()); for (size_type i(0); i < c.bucketCount(); ++i) @@ -655,10 +656,9 @@ AgedAssociativeContainerTestBase::checkUnorderedContentsRefRef(C&& c, Values con auto const last(c.end(i)); for (auto iter(c.begin(i)); iter != last; ++iter) { - auto const match( - std::find_if(v.begin(), v.end(), [iter](typename Values::value_type const& e) { - return Traits::extract(*iter) == Traits::extract(e); - })); + auto const match(std::ranges::find_if(v, [iter](Values::value_type const& e) { + return Traits::extract(*iter) == Traits::extract(e); + })); BEAST_EXPECT(match != v.end()); BEAST_EXPECT(keyEq(Traits::extract(*iter), Traits::extract(*match))); BEAST_EXPECT(hash(Traits::extract(*iter)) == hash(Traits::extract(*match))); @@ -671,7 +671,7 @@ void AgedAssociativeContainerTestBase::checkContentsRefRef(C&& c, Values const& v) { using Cont = std::remove_reference_t; - using size_type = typename Cont::size_type; + using size_type = Cont::size_type; BEAST_EXPECT(c.size() == v.size()); BEAST_EXPECT(size_type(std::distance(c.begin(), c.end())) == v.size()); @@ -703,7 +703,7 @@ AgedAssociativeContainerTestBase::checkContents(Cont& c) { using Traits = TestTraits; - using Values = typename Traits::Values; + using Values = Traits::Values; checkContents(c, Values()); } @@ -719,10 +719,10 @@ std::enable_if_t AgedAssociativeContainerTestBase::testConstructEmpty() { using Traits = TestTraits; - using Comp = typename Traits::Comp; - using Alloc = typename Traits::Alloc; - using MyComp = typename Traits::MyComp; - using MyAlloc = typename Traits::MyAlloc; + using Comp = Traits::Comp; + using Alloc = Traits::Alloc; + using MyComp = Traits::MyComp; + using MyAlloc = Traits::MyAlloc; typename Traits::ManualClock clock; // testcase (Traits::name() + " empty"); @@ -755,12 +755,12 @@ std::enable_if_t AgedAssociativeContainerTestBase::testConstructEmpty() { using Traits = TestTraits; - using Hash = typename Traits::Hash; - using Equal = typename Traits::Equal; - using Alloc = typename Traits::Alloc; - using MyHash = typename Traits::MyHash; - using MyEqual = typename Traits::MyEqual; - using MyAlloc = typename Traits::MyAlloc; + using Hash = Traits::Hash; + using Equal = Traits::Equal; + using Alloc = Traits::Alloc; + using MyHash = Traits::MyHash; + using MyEqual = Traits::MyEqual; + using MyAlloc = Traits::MyAlloc; typename Traits::ManualClock clock; // testcase (Traits::name() + " empty"); @@ -813,10 +813,10 @@ std::enable_if_t AgedAssociativeContainerTestBase::testConstructRange() { using Traits = TestTraits; - using Comp = typename Traits::Comp; - using Alloc = typename Traits::Alloc; - using MyComp = typename Traits::MyComp; - using MyAlloc = typename Traits::MyAlloc; + using Comp = Traits::Comp; + using Alloc = Traits::Alloc; + using MyComp = Traits::MyComp; + using MyAlloc = Traits::MyAlloc; typename Traits::ManualClock clock; auto const v(Traits::values()); @@ -860,12 +860,12 @@ std::enable_if_t AgedAssociativeContainerTestBase::testConstructRange() { using Traits = TestTraits; - using Hash = typename Traits::Hash; - using Equal = typename Traits::Equal; - using Alloc = typename Traits::Alloc; - using MyHash = typename Traits::MyHash; - using MyEqual = typename Traits::MyEqual; - using MyAlloc = typename Traits::MyAlloc; + using Hash = Traits::Hash; + using Equal = Traits::Equal; + using Alloc = Traits::Alloc; + using MyHash = Traits::MyHash; + using MyEqual = Traits::MyEqual; + using MyAlloc = Traits::MyAlloc; typename Traits::ManualClock clock; auto const v(Traits::values()); @@ -962,7 +962,7 @@ void AgedAssociativeContainerTestBase::testCopyMove() { using Traits = TestTraits; - using Alloc = typename Traits::Alloc; + using Alloc = Traits::Alloc; typename Traits::ManualClock clock; auto const v(Traits::values()); @@ -1307,7 +1307,7 @@ AgedAssociativeContainerTestBase::testChronological() // Test touch() with a non-const iterator. for (auto iter(v.crbegin()); iter != v.crend(); ++iter) { - using iterator = typename decltype(c)::iterator; + using iterator = decltype(c)::iterator; iterator const found(c.find(Traits::extract(*iter))); BEAST_EXPECT(found != c.cend()); @@ -1327,7 +1327,7 @@ AgedAssociativeContainerTestBase::testChronological() // Test touch() with a const_iterator for (auto iter(v.cbegin()); iter != v.cend(); ++iter) { - using const_iterator = typename decltype(c)::const_iterator; + using const_iterator = decltype(c)::const_iterator; const_iterator const found(c.find(Traits::extract(*iter))); BEAST_EXPECT(found != c.cend()); diff --git a/src/test/beast/beast_io_latency_probe_test.cpp b/src/test/beast/beast_io_latency_probe_test.cpp index 5f183ef091..b7e4980f05 100644 --- a/src/test/beast/beast_io_latency_probe_test.cpp +++ b/src/test/beast/beast_io_latency_probe_test.cpp @@ -36,8 +36,8 @@ class io_latency_probe_test : public beast::unit_test::Suite, public beast::test template struct MeasureAsioTimers { - using duration = typename Clock::duration; - using rep = typename MeasureClock::duration::rep; + using duration = Clock::duration; + using rep = MeasureClock::duration::rep; std::vector elapsedTimes; diff --git a/src/test/consensus/ByzantineFailureSim_test.cpp b/src/test/consensus/ByzantineFailureSim_test.cpp index ad75a78086..c3c51125b5 100644 --- a/src/test/consensus/ByzantineFailureSim_test.cpp +++ b/src/test/consensus/ByzantineFailureSim_test.cpp @@ -1,4 +1,3 @@ -#include #include #include #include diff --git a/src/test/consensus/Consensus_test.cpp b/src/test/consensus/Consensus_test.cpp index 629a97f0ea..92a4c67e32 100644 --- a/src/test/consensus/Consensus_test.cpp +++ b/src/test/consensus/Consensus_test.cpp @@ -1,4 +1,3 @@ -#include #include #include #include diff --git a/src/test/consensus/DistributedValidatorsSim_test.cpp b/src/test/consensus/DistributedValidatorsSim_test.cpp index 6d9ac6bede..1def09db13 100644 --- a/src/test/consensus/DistributedValidatorsSim_test.cpp +++ b/src/test/consensus/DistributedValidatorsSim_test.cpp @@ -1,4 +1,3 @@ -#include #include #include #include diff --git a/src/test/consensus/ScaleFreeSim_test.cpp b/src/test/consensus/ScaleFreeSim_test.cpp index 7e75aea72a..e533e09eb0 100644 --- a/src/test/consensus/ScaleFreeSim_test.cpp +++ b/src/test/consensus/ScaleFreeSim_test.cpp @@ -1,4 +1,3 @@ -#include #include #include #include diff --git a/src/test/csf/BasicNetwork.h b/src/test/csf/BasicNetwork.h index e1d519b30b..418cdcf289 100644 --- a/src/test/csf/BasicNetwork.h +++ b/src/test/csf/BasicNetwork.h @@ -64,9 +64,9 @@ class BasicNetwork using clock_type = Scheduler::clock_type; - using duration = typename clock_type::duration; + using duration = clock_type::duration; - using time_point = typename clock_type::time_point; + using time_point = clock_type::time_point; struct LinkType { diff --git a/src/test/csf/Digraph.h b/src/test/csf/Digraph.h index 6fbb8c3514..20e45faa5b 100644 --- a/src/test/csf/Digraph.h +++ b/src/test/csf/Digraph.h @@ -128,7 +128,7 @@ public: outVertices() const { return boost::adaptors::transform( - graph_, [](typename Graph::value_type const& v) { return v.first; }); + graph_, [](Graph::value_type const& v) { return v.first; }); } /** Range over target vertices @@ -139,7 +139,7 @@ public: [[nodiscard]] auto outVertices(Vertex source) const { - auto transform = [](typename Links::value_type const& link) { return link.first; }; + auto transform = [](Links::value_type const& link) { return link.first; }; auto it = graph_.find(source); if (it != graph_.end()) return boost::adaptors::transform(it->second, transform); @@ -165,7 +165,7 @@ public: [[nodiscard]] auto outEdges(Vertex source) const { - auto transform = [source](typename Links::value_type const& link) { + auto transform = [source](Links::value_type const& link) { return Edge{source, link.first, link.second}; }; diff --git a/src/test/csf/Scheduler.h b/src/test/csf/Scheduler.h index ede43be854..e7cbe27036 100644 --- a/src/test/csf/Scheduler.h +++ b/src/test/csf/Scheduler.h @@ -27,9 +27,9 @@ class Scheduler public: using clock_type = beast::ManualClock; - using duration = typename clock_type::duration; + using duration = clock_type::duration; - using time_point = typename clock_type::time_point; + using time_point = clock_type::time_point; private: using by_when_hook = @@ -87,14 +87,14 @@ private: class QueueType { private: - using by_when_set = typename boost::intrusive:: + using by_when_set = boost::intrusive:: make_multiset>::type; // alloc_ is owned by the scheduler boost::container::pmr::monotonic_buffer_resource* alloc_; by_when_set byWhen_; public: - using iterator = typename by_when_set::iterator; + using iterator = by_when_set::iterator; QueueType(QueueType const&) = delete; QueueType& @@ -114,7 +114,7 @@ private: end(); template - typename by_when_set::iterator + by_when_set::iterator emplace(time_point when, Handler&& h); iterator @@ -287,7 +287,7 @@ Scheduler::QueueType::end() -> iterator template inline auto -Scheduler::QueueType::emplace(time_point when, Handler&& h) -> typename by_when_set::iterator +Scheduler::QueueType::emplace(time_point when, Handler&& h) -> by_when_set::iterator { using event_type = EventImpl>; auto const p = alloc_->allocate(sizeof(event_type)); @@ -296,7 +296,7 @@ Scheduler::QueueType::emplace(time_point when, Handler&& h) -> typename by_when_ } inline auto -Scheduler::QueueType::erase(iterator iter) -> typename by_when_set::iterator +Scheduler::QueueType::erase(iterator iter) -> by_when_set::iterator { auto& e = *iter; auto next = byWhen_.erase(iter); @@ -309,7 +309,7 @@ Scheduler::QueueType::erase(iterator iter) -> typename by_when_set::iterator struct Scheduler::CancelToken { private: - typename QueueType::iterator iter_; + QueueType::iterator iter_; public: CancelToken() = delete; @@ -319,7 +319,7 @@ public: private: friend class Scheduler; - CancelToken(typename QueueType::iterator iter) : iter_(iter) + CancelToken(QueueType::iterator iter) : iter_(iter) { } }; diff --git a/src/test/csf/SimTime.h b/src/test/csf/SimTime.h index e38a375e02..125674f15d 100644 --- a/src/test/csf/SimTime.h +++ b/src/test/csf/SimTime.h @@ -11,7 +11,7 @@ using RealDuration = RealClock::duration; using RealTime = RealClock::time_point; using SimClock = beast::ManualClock; -using SimDuration = typename SimClock::duration; -using SimTime = typename SimClock::time_point; +using SimDuration = SimClock::duration; +using SimTime = SimClock::time_point; } // namespace xrpl::test::csf diff --git a/src/test/csf/random.h b/src/test/csf/random.h index 08002aed7f..30f98e37fe 100644 --- a/src/test/csf/random.h +++ b/src/test/csf/random.h @@ -72,14 +72,14 @@ public: Selector(RAIter first, RAIter last, std::vector const& w, Generator& g) : first_{first}, last_{last}, dd_{w.begin(), w.end()}, g_{g} { - using tag = typename std::iterator_traits::iterator_category; + using tag = std::iterator_traits::iterator_category; static_assert( std::is_same_v, "Selector only supports random access iterators."); // TODO: Allow for forward iterators } - typename std::iterator_traits::value_type + std::iterator_traits::value_type operator()() { auto idx = dd_(g_); diff --git a/src/test/jtx/TestHelpers.h b/src/test/jtx/TestHelpers.h index 27c54d830b..0e35e6b9ec 100644 --- a/src/test/jtx/TestHelpers.h +++ b/src/test/jtx/TestHelpers.h @@ -27,6 +27,7 @@ namespace xrpl::test::jtx { */ template < class SField, + // NOLINTNEXTLINE(readability-redundant-typename): typename required by MSVC class StoredValue = typename SField::type::value_type, class OutputValue = StoredValue> struct JTxField @@ -213,8 +214,8 @@ template struct JTxFieldWrapper { using JF = JTxField; - using SF = typename JF::SF; - using SV = typename JF::SV; + using SF = JF::SF; + using SV = JF::SV; protected: SF const& sfield_; @@ -266,9 +267,11 @@ public: } }; +// NOLINTNEXTLINE(readability-redundant-typename): typename required by MSVC template using valueUnitWrapper = JTxFieldWrapper>; +// NOLINTNEXTLINE(readability-redundant-typename): typename required by MSVC template using simpleField = JTxFieldWrapper>; diff --git a/src/test/nodestore/Timing_test.cpp b/src/test/nodestore/Timing_test.cpp index f5e6bf8aa4..e308d0d5ff 100644 --- a/src/test/nodestore/Timing_test.cpp +++ b/src/test/nodestore/Timing_test.cpp @@ -57,7 +57,7 @@ template static void rngcpy(void* buffer, std::size_t bytes, Generator& g) { - using result_type = typename Generator::result_type; + using result_type = Generator::result_type; while (bytes >= sizeof(result_type)) { auto const v = g(); diff --git a/src/test/server/Server_test.cpp b/src/test/server/Server_test.cpp index 54091ef767..9ff0015b5d 100644 --- a/src/test/server/Server_test.cpp +++ b/src/test/server/Server_test.cpp @@ -169,7 +169,7 @@ public: // Connect to an address template bool - connect(Socket& s, typename Socket::endpoint_type const& ep) + connect(Socket& s, Socket::endpoint_type const& ep) { try { diff --git a/src/test/unit_test/multi_runner.cpp b/src/test/unit_test/multi_runner.cpp index 3a56d22654..71208313a4 100644 --- a/src/test/unit_test/multi_runner.cpp +++ b/src/test/unit_test/multi_runner.cpp @@ -69,9 +69,7 @@ Results::add(SuiteResults const& r) top.begin(), top.end(), elapsed, - [](run_time const& t1, typename clock_type::duration const& t2) { - return t1.second > t2; - }); + [](run_time const& t1, clock_type::duration const& t2) { return t1.second > t2; }); if (iter != top.end()) { diff --git a/src/test/unit_test/multi_runner.h b/src/test/unit_test/multi_runner.h index 8b07559e8c..55cf6c25fa 100644 --- a/src/test/unit_test/multi_runner.h +++ b/src/test/unit_test/multi_runner.h @@ -42,7 +42,7 @@ struct SuiteResults std::size_t cases = 0; std::size_t total = 0; std::size_t failed = 0; - typename clock_type::time_point start = clock_type::now(); + clock_type::time_point start = clock_type::now(); explicit SuiteResults(std::string name = "") : name(std::move(name)) { @@ -57,7 +57,7 @@ struct Results using static_string = boost::beast::static_string<256>; // results may be stored in shared memory. Use `static_string` to ensure // pointers from different memory spaces do not co-mingle - using run_time = std::pair; + using run_time = std::pair; static constexpr auto kMaxTop = 10; @@ -66,7 +66,7 @@ struct Results std::size_t total = 0; std::size_t failed = 0; boost::container::static_vector top; - typename clock_type::time_point start = clock_type::now(); + clock_type::time_point start = clock_type::now(); void add(SuiteResults const& r); diff --git a/src/xrpld/app/consensus/RCLConsensus.cpp b/src/xrpld/app/consensus/RCLConsensus.cpp index a474c9c339..a7c2b26c04 100644 --- a/src/xrpld/app/consensus/RCLConsensus.cpp +++ b/src/xrpld/app/consensus/RCLConsensus.cpp @@ -580,7 +580,9 @@ RCLConsensus::Adaptor::doAccept( JLOG(j_.info()) << "CNF Val " << newLCLHash; } else + { JLOG(j_.info()) << "CNF buildLCL " << newLCLHash; + } // See if we can accept a ledger as fully-validated ledgerMaster_.consensusBuilt(built.ledger, result.txns.id(), std::move(consensusJson)); @@ -796,7 +798,9 @@ RCLConsensus::Adaptor::buildLCL( JLOG(j_.debug()) << "Consensus built ledger we were acquiring"; } else + { JLOG(j_.debug()) << "Consensus built new ledger"; + } return RCLCxLedger{std::move(built)}; } diff --git a/src/xrpld/app/consensus/RCLValidations.cpp b/src/xrpld/app/consensus/RCLValidations.cpp index 02ff86b23d..9d40e60b00 100644 --- a/src/xrpld/app/consensus/RCLValidations.cpp +++ b/src/xrpld/app/consensus/RCLValidations.cpp @@ -46,8 +46,10 @@ RCLValidatedLedger::RCLValidatedLedger( ancestors_ = hashIndex->getFieldV256(sfHashes).value(); } else + { JLOG(j_.warn()) << "Ledger " << ledgerSeq_ << ":" << ledgerID_ << " missing recent ancestor hashes"; + } } auto diff --git a/src/xrpld/app/ledger/LedgerHistory.cpp b/src/xrpld/app/ledger/LedgerHistory.cpp index 8520fc941f..b7e1772942 100644 --- a/src/xrpld/app/ledger/LedgerHistory.cpp +++ b/src/xrpld/app/ledger/LedgerHistory.cpp @@ -368,8 +368,10 @@ LedgerHistory::handleMismatch( << " validated: " << to_string(*validatedConsensusHash); } else + { JLOG(j_.error()) << "MISMATCH with same consensus transaction set: " << to_string(*builtConsensusHash); + } } // Find differences between built and valid ledgers @@ -381,8 +383,10 @@ LedgerHistory::handleMismatch( JLOG(j_.error()) << "MISMATCH with same " << builtTx.size() << " transactions"; } else + { JLOG(j_.error()) << "MISMATCH with " << builtTx.size() << " built and " << validTx.size() << " valid transactions."; + } JLOG(j_.error()) << "built\n" << getJson({*builtLedger, {}}); JLOG(j_.error()) << "valid\n" << getJson({*validLedger, {}}); diff --git a/src/xrpld/app/ledger/detail/BuildLedger.cpp b/src/xrpld/app/ledger/detail/BuildLedger.cpp index a77c1c9c50..2a4121ede9 100644 --- a/src/xrpld/app/ledger/detail/BuildLedger.cpp +++ b/src/xrpld/app/ledger/detail/BuildLedger.cpp @@ -204,9 +204,11 @@ buildLedger( << accum.txCount(); } else + { JLOG(j.debug()) << "Applied " << applied << " transactions. " << "Total transactions in ledger (including Inner Batch): " << accum.txCount(); + } }); } diff --git a/src/xrpld/app/ledger/detail/LedgerCleaner.cpp b/src/xrpld/app/ledger/detail/LedgerCleaner.cpp index 9f2db9d2f2..b96f01e577 100644 --- a/src/xrpld/app/ledger/detail/LedgerCleaner.cpp +++ b/src/xrpld/app/ledger/detail/LedgerCleaner.cpp @@ -366,7 +366,9 @@ private: } } else + { JLOG(j_.warn()) << "Validated ledger is prior to target ledger"; + } return ledgerHash; } diff --git a/src/xrpld/app/ledger/detail/LedgerMaster.cpp b/src/xrpld/app/ledger/detail/LedgerMaster.cpp index 9baad0ec90..31510b44d2 100644 --- a/src/xrpld/app/ledger/detail/LedgerMaster.cpp +++ b/src/xrpld/app/ledger/detail/LedgerMaster.cpp @@ -755,7 +755,9 @@ LedgerMaster::getFetchPack(LedgerIndex missing, InboundLedger::Reason reason) JLOG(journal_.trace()) << "Requested fetch pack for " << missing; } else + { JLOG(journal_.debug()) << "No peer for fetch pack"; + } } void @@ -1797,10 +1799,14 @@ LedgerMaster::fetchForHistory( getFetchPack(missing, reason); } else + { JLOG(journal_.trace()) << "fetchForHistory no fetch pack for " << missing; + } } else + { JLOG(journal_.debug()) << "fetchForHistory found failed acquire"; + } } if (ledger) { diff --git a/src/xrpld/app/main/Application.cpp b/src/xrpld/app/main/Application.cpp index 67b5e30eb7..c2fb78ce79 100644 --- a/src/xrpld/app/main/Application.cpp +++ b/src/xrpld/app/main/Application.cpp @@ -1612,7 +1612,9 @@ ApplicationImp::signalStop(std::string const& msg) JLOG(journal_.warn()) << "Server stopping"; } else + { JLOG(journal_.warn()) << "Server stopping: " << msg; + } isTimeToStop.notify_all(); } diff --git a/src/xrpld/app/misc/NetworkOPs.cpp b/src/xrpld/app/misc/NetworkOPs.cpp index d807dea10a..1802441a66 100644 --- a/src/xrpld/app/misc/NetworkOPs.cpp +++ b/src/xrpld/app/misc/NetworkOPs.cpp @@ -1687,11 +1687,13 @@ NetworkOPsImp::apply(std::unique_lock& batchLock) e.transaction->setKept(); } else + { JLOG(journal_.debug()) << "Not holding transaction " << e.transaction->getID() << ": " << (e.local ? "local" : "network") << ", " << "result: " << e.result << " ledgers left: " << (ledgersLeft ? to_string(*ledgersLeft) : "unspecified"); + } } } else diff --git a/src/xrpld/app/misc/detail/Transaction.cpp b/src/xrpld/app/misc/detail/Transaction.cpp index 425a5723fb..2c55c474eb 100644 --- a/src/xrpld/app/misc/detail/Transaction.cpp +++ b/src/xrpld/app/misc/detail/Transaction.cpp @@ -73,7 +73,7 @@ Transaction::setStatus( TransStatus Transaction::sqlTransactionStatus(boost::optional const& status) { - auto const c = (status) ? safeCast((*status)[0]) : TxnSql::Unknown; + auto const c = status ? safeCast((*status)[0]) : TxnSql::Unknown; switch (static_cast(c)) { diff --git a/src/xrpld/app/misc/detail/ValidatorSite.cpp b/src/xrpld/app/misc/detail/ValidatorSite.cpp index 76fd078174..6ce3711652 100644 --- a/src/xrpld/app/misc/detail/ValidatorSite.cpp +++ b/src/xrpld/app/misc/detail/ValidatorSite.cpp @@ -339,8 +339,10 @@ ValidatorSite::onRequestTimeout(std::size_t siteIdx, error_code const& ec) JLOG(j_.warn()) << "Request for " << site.activeResource->uri << " took too long"; } else + { JLOG(j_.error()) << "Request took too long, but a response has " "already been processed"; + } } std::scoped_lock const lockState{stateMutex_}; diff --git a/src/xrpld/app/rdb/backend/detail/Node.cpp b/src/xrpld/app/rdb/backend/detail/Node.cpp index 9b7db6f0f5..dcc146397b 100644 --- a/src/xrpld/app/rdb/backend/detail/Node.cpp +++ b/src/xrpld/app/rdb/backend/detail/Node.cpp @@ -125,7 +125,7 @@ makeLedgerDBs( std::size_t notnull = 0, dfltValue = 0, pk = 0; soci::indicator ind = soci::i_null; soci::statement st = - (tx->getSession().prepare << ("PRAGMA table_info(AccountTransactions);"), + (tx->getSession().prepare << "PRAGMA table_info(AccountTransactions);", soci::into(cid), soci::into(name), soci::into(type), @@ -1065,10 +1065,10 @@ accountTxPage( if (findLedger == 0) { sql = boost::str( - boost::format(kPrefix + (R"(AccountTransactions.LedgerSeq BETWEEN %u AND %u + boost::format(kPrefix + R"(AccountTransactions.LedgerSeq BETWEEN %u AND %u ORDER BY AccountTransactions.LedgerSeq %s, AccountTransactions.TxnSeq %s - LIMIT %u;)")) % + LIMIT %u;)") % toBase58(options.account) % options.ledgerRange.min % options.ledgerRange.max % order % order % queryLimit); } @@ -1080,7 +1080,7 @@ accountTxPage( auto b58acct = toBase58(options.account); sql = boost::str( - boost::format(( + boost::format( R"(SELECT AccountTransactions.LedgerSeq,AccountTransactions.TxnSeq, Status,RawTxn,TxnMeta FROM AccountTransactions, Transactions WHERE @@ -1097,7 +1097,7 @@ accountTxPage( ORDER BY AccountTransactions.LedgerSeq %s, AccountTransactions.TxnSeq %s LIMIT %u; - )")) % + )") % b58acct % minLedger % maxLedger % b58acct % findLedger % compare % findSeq % order % order % queryLimit); } diff --git a/src/xrpld/consensus/Consensus.h b/src/xrpld/consensus/Consensus.h index 131db30ce0..b8d04e18b5 100644 --- a/src/xrpld/consensus/Consensus.h +++ b/src/xrpld/consensus/Consensus.h @@ -276,11 +276,11 @@ checkConsensus( template class Consensus { - using Ledger_t = typename Adaptor::Ledger_t; - using TxSet_t = typename Adaptor::TxSet_t; - using NodeID_t = typename Adaptor::NodeID_t; - using Tx_t = typename TxSet_t::Tx; - using PeerPosition_t = typename Adaptor::PeerPosition_t; + using Ledger_t = Adaptor::Ledger_t; + using TxSet_t = Adaptor::TxSet_t; + using NodeID_t = Adaptor::NodeID_t; + using Tx_t = TxSet_t::Tx; + using PeerPosition_t = Adaptor::PeerPosition_t; using Proposal_t = ConsensusProposal; using Result = ConsensusResult; @@ -341,7 +341,7 @@ public: void startRound( NetClock::time_point const& now, - typename Ledger_t::ID const& prevLedgerID, + Ledger_t::ID const& prevLedgerID, Ledger_t prevLedger, hash_set const& nowUntrusted, bool proposing, @@ -402,7 +402,7 @@ public: @return ID of previous ledger */ - typename Ledger_t::ID + Ledger_t::ID prevLedgerID() const { return prevLedgerID_; @@ -428,16 +428,14 @@ private: void startRoundInternal( NetClock::time_point const& now, - typename Ledger_t::ID const& prevLedgerID, + Ledger_t::ID const& prevLedgerID, Ledger_t const& prevLedger, ConsensusMode mode, std::unique_ptr const& clog); // Change our view of the previous ledger void - handleWrongLedger( - typename Ledger_t::ID const& lgrId, - std::unique_ptr const& clog); + handleWrongLedger(Ledger_t::ID const& lgrId, std::unique_ptr const& clog); /** Check if our previous ledger matches the network's. @@ -568,7 +566,7 @@ private: // Non-peer (self) consensus data // Last validated ledger ID provided to consensus - typename Ledger_t::ID prevLedgerID_; + Ledger_t::ID prevLedgerID_; // Last validated ledger seen by consensus Ledger_t previousLedger_; @@ -616,7 +614,7 @@ template void Consensus::startRound( NetClock::time_point const& now, - typename Ledger_t::ID const& prevLedgerID, + Ledger_t::ID const& prevLedgerID, Ledger_t prevLedger, hash_set const& nowUntrusted, bool proposing, @@ -661,7 +659,7 @@ template void Consensus::startRoundInternal( NetClock::time_point const& now, - typename Ledger_t::ID const& prevLedgerID, + Ledger_t::ID const& prevLedgerID, Ledger_t const& prevLedger, ConsensusMode mode, std::unique_ptr const& clog) @@ -811,7 +809,9 @@ Consensus::peerProposalInternal( gotTxSet(now_, *set); } else + { JLOG(j_.debug()) << "Don't have tx set for peer"; + } } else if (result_) { @@ -1025,7 +1025,7 @@ Consensus::getJson(bool full) const template void Consensus::handleWrongLedger( - typename Ledger_t::ID const& lgrId, + Ledger_t::ID const& lgrId, std::unique_ptr const& clog) { CLOG(clog) << "handleWrongLedger. "; diff --git a/src/xrpld/consensus/ConsensusTypes.h b/src/xrpld/consensus/ConsensusTypes.h index 64a7f5fdea..f043fc0663 100644 --- a/src/xrpld/consensus/ConsensusTypes.h +++ b/src/xrpld/consensus/ConsensusTypes.h @@ -183,11 +183,11 @@ enum class ConsensusState { template struct ConsensusResult { - using Ledger_t = typename Traits::Ledger_t; - using TxSet_t = typename Traits::TxSet_t; - using NodeID_t = typename Traits::NodeID_t; + using Ledger_t = Traits::Ledger_t; + using TxSet_t = Traits::TxSet_t; + using NodeID_t = Traits::NodeID_t; - using Tx_t = typename TxSet_t::Tx; + using Tx_t = TxSet_t::Tx; using Proposal_t = ConsensusProposal; using Dispute_t = DisputedTx; diff --git a/src/xrpld/consensus/DisputedTx.h b/src/xrpld/consensus/DisputedTx.h index 1c0c069f54..ba8329714b 100644 --- a/src/xrpld/consensus/DisputedTx.h +++ b/src/xrpld/consensus/DisputedTx.h @@ -29,7 +29,7 @@ namespace xrpl { template class DisputedTx { - using TxID_t = typename Tx::ID; + using TxID_t = Tx::ID; using Map_t = boost::container::flat_map; public: diff --git a/src/xrpld/consensus/LedgerTrie.h b/src/xrpld/consensus/LedgerTrie.h index 9d76c7f283..cd9662ff02 100644 --- a/src/xrpld/consensus/LedgerTrie.h +++ b/src/xrpld/consensus/LedgerTrie.h @@ -21,8 +21,8 @@ template class SpanTip { public: - using Seq = typename Ledger::Seq; - using ID = typename Ledger::ID; + using Seq = Ledger::Seq; + using ID = Ledger::ID; SpanTip(Seq s, ID i, Ledger const lgr) : seq{s}, id{i}, ledger_{std::move(lgr)} { @@ -58,8 +58,8 @@ namespace ledger_trie_detail { template class Span { - using Seq = typename Ledger::Seq; - using ID = typename Ledger::ID; + using Seq = Ledger::Seq; + using ID = Ledger::ID; // The span is the half-open interval [start,end) of ledger_ Seq start_{0}; @@ -323,8 +323,8 @@ struct Node template class LedgerTrie { - using Seq = typename Ledger::Seq; - using ID = typename Ledger::ID; + using Seq = Ledger::Seq; + using ID = Ledger::ID; using Node = ledger_trie_detail::Node; using Span = ledger_trie_detail::Span; diff --git a/src/xrpld/consensus/Validations.h b/src/xrpld/consensus/Validations.h index 2f5762ce83..f109ae620b 100644 --- a/src/xrpld/consensus/Validations.h +++ b/src/xrpld/consensus/Validations.h @@ -267,13 +267,13 @@ to_string(ValStatus m) template class Validations { - using Mutex = typename Adaptor::Mutex; - using Validation = typename Adaptor::Validation; - using Ledger = typename Adaptor::Ledger; - using ID = typename Ledger::ID; - using Seq = typename Ledger::Seq; - using NodeID = typename Validation::NodeID; - using NodeKey = typename Validation::NodeKey; + using Mutex = Adaptor::Mutex; + using Validation = Adaptor::Validation; + using Ledger = Adaptor::Ledger; + using ID = Ledger::ID; + using Seq = Ledger::Seq; + using NodeID = Validation::NodeID; + using NodeKey = Validation::NodeKey; using WrappedValidationType = std::decay_t>; diff --git a/src/xrpld/overlay/Slot.h b/src/xrpld/overlay/Slot.h index 0600265500..7490798787 100644 --- a/src/xrpld/overlay/Slot.h +++ b/src/xrpld/overlay/Slot.h @@ -82,7 +82,7 @@ class Slot final private: friend class Slots; using id_t = Peer::id_t; - using time_point = typename ClockType::time_point; + using time_point = ClockType::time_point; // a callback to report ignored squelches using ignored_squelch_callback = std::function; @@ -217,7 +217,7 @@ private: std::uint16_t reachedThreshold_{0}; // last time peers were selected, used to age the slot - typename ClockType::time_point lastSelected_; + ClockType::time_point lastSelected_; SlotState state_{SlotState::Counting}; // slot's state SquelchHandler const& handler_; // squelch/unsquelch handler @@ -483,7 +483,7 @@ Slot::notInState(PeerState state) const } template -std::set +std::set Slot::getSelected() const { std::set r; @@ -496,7 +496,7 @@ Slot::getSelected() const } template -std::unordered_map> +std::unordered_map> Slot::getPeers() const { using namespace std::chrono; @@ -526,8 +526,8 @@ Slot::getPeers() const template class Slots final { - using time_point = typename ClockType::time_point; - using id_t = typename Peer::id_t; + using time_point = ClockType::time_point; + using id_t = Peer::id_t; using messages = beast::aged_unordered_map< uint256, std::unordered_set, @@ -600,7 +600,7 @@ public: PublicKey const& validator, id_t id, protocol::MessageType type, - typename Slot::ignored_squelch_callback callback); + Slot::ignored_squelch_callback callback); /** Check if peers stopped relaying messages * and if slots stopped receiving messages from the validator. @@ -651,9 +651,8 @@ public: /** Get peers info. Return map of peer's state, count, and squelch * expiration milliseconds. */ - std:: - unordered_map> - getPeers(PublicKey const& validator) + std::unordered_map> + getPeers(PublicKey const& validator) { auto const& it = slots_.find(validator); if (it != slots_.end()) @@ -742,7 +741,7 @@ Slots::updateSlotAndSquelch( PublicKey const& validator, id_t id, protocol::MessageType type, - typename Slot::ignored_squelch_callback callback) + Slot::ignored_squelch_callback callback) { if (!addPeerMessage(key, id)) return; diff --git a/src/xrpld/overlay/Squelch.h b/src/xrpld/overlay/Squelch.h index b509f293c2..96d8c26f1d 100644 --- a/src/xrpld/overlay/Squelch.h +++ b/src/xrpld/overlay/Squelch.h @@ -14,7 +14,7 @@ namespace xrpl::reduce_relay { template class Squelch { - using time_point = typename ClockType::time_point; + using time_point = ClockType::time_point; public: explicit Squelch(beast::Journal journal) : journal_(journal) diff --git a/src/xrpld/overlay/detail/PeerImp.h b/src/xrpld/overlay/detail/PeerImp.h index 26d7e0a832..28fb6b33a4 100644 --- a/src/xrpld/overlay/detail/PeerImp.h +++ b/src/xrpld/overlay/detail/PeerImp.h @@ -293,7 +293,7 @@ public: /** Send a set of PeerFinder endpoints as a protocol message. */ template < class FwdIt, - class = typename std::enable_if_t< + class = std::enable_if_t< std::is_same_v::value_type, PeerFinder::Endpoint>>> void sendEndpoints(FwdIt first, FwdIt last); diff --git a/src/xrpld/overlay/detail/ZeroCopyStream.h b/src/xrpld/overlay/detail/ZeroCopyStream.h index d8d311105d..f77f266321 100644 --- a/src/xrpld/overlay/detail/ZeroCopyStream.h +++ b/src/xrpld/overlay/detail/ZeroCopyStream.h @@ -17,7 +17,7 @@ template class ZeroCopyInputStream : public ::google::protobuf::io::ZeroCopyInputStream { private: - using iterator = typename Buffers::const_iterator; + using iterator = Buffers::const_iterator; using const_buffer = boost::asio::const_buffer; google::protobuf::int64 count_ = 0; @@ -110,8 +110,8 @@ template class ZeroCopyOutputStream : public ::google::protobuf::io::ZeroCopyOutputStream { private: - using buffers_type = typename Streambuf::mutable_buffers_type; - using iterator = typename buffers_type::const_iterator; + using buffers_type = Streambuf::mutable_buffers_type; + using iterator = buffers_type::const_iterator; using mutable_buffer = boost::asio::mutable_buffer; Streambuf& streambuf_; diff --git a/src/xrpld/peerfinder/detail/Checker.h b/src/xrpld/peerfinder/detail/Checker.h index 8ab084830c..2f324bf8b6 100644 --- a/src/xrpld/peerfinder/detail/Checker.h +++ b/src/xrpld/peerfinder/detail/Checker.h @@ -34,8 +34,8 @@ private: template struct AsyncOp : BasicAsyncOp { - using socket_type = typename Protocol::socket; - using endpoint_type = typename Protocol::endpoint; + using socket_type = Protocol::socket; + using endpoint_type = Protocol::endpoint; Checker& checker; socket_type socket; @@ -57,8 +57,8 @@ private: //-------------------------------------------------------------------------- - using list_type = typename boost::intrusive:: - make_list>::type; + using list_type = + boost::intrusive::make_list>::type; std::mutex mutex_; std::condition_variable cond_; diff --git a/src/xrpld/peerfinder/detail/Livecache.h b/src/xrpld/peerfinder/detail/Livecache.h index 84efcb7bd1..c5f04be90a 100644 --- a/src/xrpld/peerfinder/detail/Livecache.h +++ b/src/xrpld/peerfinder/detail/Livecache.h @@ -65,12 +65,12 @@ public: }; public: - using iterator = boost::transform_iterator; + using iterator = boost::transform_iterator; using const_iterator = iterator; using reverse_iterator = - boost::transform_iterator; + boost::transform_iterator; using const_reverse_iterator = reverse_iterator; @@ -132,7 +132,7 @@ public: } private: - explicit Hop(typename beast::MaybeConst::type& list) : list_(list) + explicit Hop(beast::MaybeConst::type& list) : list_(list) { } @@ -145,7 +145,7 @@ protected: // Work-around to call Hop's private constructor from Livecache template static Hop - makeHop(typename beast::MaybeConst::type& list) + makeHop(beast::MaybeConst::type& list) { return Hop(list); } @@ -208,30 +208,29 @@ public: template struct Transform { - using first_argument = typename lists_type::value_type; + using first_argument = lists_type::value_type; using result_type = Hop; explicit Transform() = default; Hop - operator()(typename beast::MaybeConst::type& - list) const + operator()(beast::MaybeConst::type& list) const { return makeHop(list); } }; public: - using iterator = boost::transform_iterator, typename lists_type::iterator>; + using iterator = boost::transform_iterator, lists_type::iterator>; using const_iterator = - boost::transform_iterator, typename lists_type::const_iterator>; + boost::transform_iterator, lists_type::const_iterator>; using reverse_iterator = - boost::transform_iterator, typename lists_type::reverse_iterator>; + boost::transform_iterator, lists_type::reverse_iterator>; using const_reverse_iterator = - boost::transform_iterator, typename lists_type::const_reverse_iterator>; + boost::transform_iterator, lists_type::const_reverse_iterator>; iterator begin() @@ -338,7 +337,7 @@ public: } /** Returns the number of entries in the cache. */ - typename cache_type::size_type + cache_type::size_type size() const { return cache_.size(); diff --git a/src/xrpld/peerfinder/detail/Logic.h b/src/xrpld/peerfinder/detail/Logic.h index 815858cf00..55cce506ba 100644 --- a/src/xrpld/peerfinder/detail/Logic.h +++ b/src/xrpld/peerfinder/detail/Logic.h @@ -980,7 +980,7 @@ public: /** Adds eligible Fixed addresses for outbound attempts. */ template void - getFixed(std::size_t needed, Container& c, typename ConnectHandouts::Squelches& squelches) + getFixed(std::size_t needed, Container& c, ConnectHandouts::Squelches& squelches) { auto const now(clock.now()); for (auto iter = fixed_.begin(); needed && iter != fixed_.end(); ++iter) diff --git a/src/xrpld/rpc/detail/RPCCall.cpp b/src/xrpld/rpc/detail/RPCCall.cpp index f405ffe4de..123b9fc7a5 100644 --- a/src/xrpld/rpc/detail/RPCCall.cpp +++ b/src/xrpld/rpc/detail/RPCCall.cpp @@ -1589,7 +1589,7 @@ struct RPCCallImp jvResult["result"] = jvReply; - (callbackFuncP)(jvResult); + callbackFuncP(jvResult); } return false; diff --git a/src/xrpld/rpc/handlers/admin/keygen/WalletPropose.cpp b/src/xrpld/rpc/handlers/admin/keygen/WalletPropose.cpp index c783319049..4b5f1821e3 100644 --- a/src/xrpld/rpc/handlers/admin/keygen/WalletPropose.cpp +++ b/src/xrpld/rpc/handlers/admin/keygen/WalletPropose.cpp @@ -39,7 +39,7 @@ estimateEntropy(std::string const& input) { (void)_; auto x = f / input.length(); - se += (x)*log2(x); + se += x * log2(x); } // We multiply it by the length, to get an estimate of diff --git a/src/xrpld/rpc/json_body.h b/src/xrpld/rpc/json_body.h index 4520a8bf39..5c4c56cef8 100644 --- a/src/xrpld/rpc/json_body.h +++ b/src/xrpld/rpc/json_body.h @@ -22,7 +22,7 @@ struct JsonBody dynamic_buffer_type buffer_; public: - using const_buffers_type = typename dynamic_buffer_type::const_buffers_type; + using const_buffers_type = dynamic_buffer_type::const_buffers_type; using is_deferred = std::false_type; From 556d62a0deee94cc55b2f9cfb29e29dd7926aa1c Mon Sep 17 00:00:00 2001 From: Michael Legleux Date: Wed, 24 Jun 2026 16:53:46 -0700 Subject: [PATCH 12/14] build: Align xrpld RPM packaging with DEB package (#7529) --- .github/workflows/reusable-package.yml | 20 +--- cmake/XrplPackaging.cmake | 1 - cspell.config.yaml | 1 + package/README.md | 159 ++++++++++++++++--------- package/build_pkg.sh | 148 ++++++++++++----------- package/rpm/xrpld.spec | 22 +++- package/shared/50-xrpld.preset | 2 - 7 files changed, 203 insertions(+), 150 deletions(-) delete mode 100644 package/shared/50-xrpld.preset diff --git a/.github/workflows/reusable-package.yml b/.github/workflows/reusable-package.yml index eed4bfc4a3..249e807592 100644 --- a/.github/workflows/reusable-package.yml +++ b/.github/workflows/reusable-package.yml @@ -39,23 +39,8 @@ jobs: working-directory: .github/scripts/strategy-matrix run: ./generate.py --packaging >>"${GITHUB_OUTPUT}" - generate-version: - runs-on: ubuntu-latest - outputs: - version: ${{ steps.version.outputs.version }} - steps: - - name: Checkout repository - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - with: - sparse-checkout: | - .github/actions/generate-version - src/libxrpl/protocol/BuildInfo.cpp - - name: Generate version - id: version - uses: ./.github/actions/generate-version - package: - needs: [generate-matrix, generate-version] + needs: [generate-matrix] if: ${{ github.event.repository.visibility == 'public' }} strategy: fail-fast: false @@ -82,14 +67,13 @@ jobs: - name: Build package env: - PKG_VERSION: ${{ needs.generate-version.outputs.version }} PKG_RELEASE: ${{ inputs.pkg_release }} run: ./package/build_pkg.sh - name: Upload package artifact uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: - name: ${{ matrix.artifact_name }}-pkg-${{ needs.generate-version.outputs.version }} + name: ${{ matrix.artifact_name }}-pkg path: | ${{ env.BUILD_DIR }}/debbuild/*.deb ${{ env.BUILD_DIR }}/debbuild/*.ddeb diff --git a/cmake/XrplPackaging.cmake b/cmake/XrplPackaging.cmake index fe885c200c..8e3861925d 100644 --- a/cmake/XrplPackaging.cmake +++ b/cmake/XrplPackaging.cmake @@ -28,7 +28,6 @@ endif() set(package_env SRC_DIR=${CMAKE_SOURCE_DIR} BUILD_DIR=${CMAKE_BINARY_DIR} - PKG_VERSION=${xrpld_version} PKG_RELEASE=${pkg_release} ) diff --git a/cspell.config.yaml b/cspell.config.yaml index 0d38c4be7b..8273df6c98 100644 --- a/cspell.config.yaml +++ b/cspell.config.yaml @@ -301,6 +301,7 @@ words: - txs - ubsan - UBSAN + - ufdio - umant - unacquired - unambiguity diff --git a/package/README.md b/package/README.md index 63c2ab88fc..4b78106c4c 100644 --- a/package/README.md +++ b/package/README.md @@ -6,10 +6,10 @@ This directory contains all files needed to build RPM and Debian packages for `x ``` package/ - build_pkg.sh Staging and build script (called by CMake targets and CI) + build_pkg.sh Staging and build script (called by the CMake `package` target and CI) rpm/ - xrpld.spec RPM spec (xrpld_version/pkg_release passed via rpmbuild --define) - debian/ Debian control files (control, rules, install, links, conffiles, ...) + xrpld.spec RPM spec + debian/ Debian control files (control, rules, copyright, xrpld.docs, xrpld.links, source/format) shared/ xrpld.service systemd unit file (used by both RPM and DEB) xrpld.sysusers sysusers.d config (used by both RPM and DEB) @@ -21,21 +21,19 @@ package/ Packaging targets and their container images are declared in [`.github/scripts/strategy-matrix/linux.json`](../.github/scripts/strategy-matrix/linux.json) -inside `package_configs` configurations. Today only -`linux/amd64` is emitted. The package format -(deb or rpm) is inferred at build time from the container's package manager -(`apt-get` -> deb, `dnf`/`yum` -> rpm). The image tag is composed as -`ghcr.io/xrplf/xrpld/packaging-:sha-` — -the same scheme used by `reusable-build-test.yml`. Bump `image_sha` in -`linux.json` and both CI and local builds pick up the new image with no -workflow edits. +under `package_configs`, one entry per distro. Today only `linux/amd64` is +emitted. Each entry pins its full container image in an `image` field; to move +to a new image, edit that field and both CI and local builds pick it up. The +package format (deb or rpm) is inferred at build time from the container's +package manager (`apt-get` -> deb, `dnf`/`yum` -> rpm). -| Package type | Image (derived from `linux.json`) | Tool required | -| ------------ | ---------------------------------------------------- | --------------------------------------------------------------- | -| RPM | `ghcr.io/xrplf/xrpld/packaging-rhel:sha-` | `rpmbuild` | -| DEB | `ghcr.io/xrplf/xrpld/packaging-debian:sha-` | `dpkg-buildpackage`, `debhelper (>= 13)`, `dh-sequence-systemd` | +| Package type | Image (`package_configs.[].image` in `linux.json`) | Tools required | +| ------------ | ---------------------------------------------------------- | --------------------------------------------------- | +| RPM | `ghcr.io/xrplf/xrpld/packaging-rhel:sha-` | `rpmbuild` | +| DEB | `ghcr.io/xrplf/xrpld/packaging-debian:sha-` | `dpkg-buildpackage`, debhelper with compat level 13 | -To print the exact image tags for the current `linux.json`: +To print the full packaging matrix (artifact names and images) for the current +`linux.json`: ```bash ./.github/scripts/strategy-matrix/generate.py --packaging @@ -46,12 +44,13 @@ To print the exact image tags for the current `linux.json`: ### Via CI Caller workflows (`on-pr.yml`, `on-tag.yml`, `on-trigger.yml`) call -`reusable-strategy-matrix.yml` with `mode: packaging` to generate the matrix of -`{artifact_name, os}` entries, then fan out to -`reusable-package.yml` per entry. That workflow downloads the pre-built `xrpld` -binary artifact, detects the package format from the container, and calls -`build_pkg.sh` directly — no CMake configure or build step is needed inside -the packaging job. +`reusable-package.yml`. That workflow generates its own packaging matrix from +`package_configs` in `linux.json` (via `generate.py --packaging`) and fans out +one job per distro. Each job downloads the pre-built `xrpld` binary artifact and +runs in that distro's container, so the package format follows from the +container's package manager. The packaging script derives the package version +from the downloaded binary's `xrpld --version` output; no CMake configure or +build step is needed inside the packaging job. ### Locally (mirrors CI) @@ -60,22 +59,19 @@ inside the same container CI uses. The image tag is derived from `linux.json` so you don't need to hardcode a SHA. ```bash -# From the repo root. Pick any image flagged with `"package": true` in -# linux.json; the package format is inferred from the container's package -# manager. Example for the rpm-producing image: -IMAGE=$(jq -r ' - .os | map(select(.package == true))[0] | - "ghcr.io/xrplf/ci/\(.distro_name)-\(.distro_version):\(.compiler_name)-\(.compiler_version)-sha-\(.image_sha)" -' .github/scripts/strategy-matrix/linux.json) +# From the repo root. Each distro's container image is the `image` field of its +# package_configs entry in linux.json; the package format is inferred from the +# container's package manager. Example for the rpm-producing image (use +# .package_configs.debian[0].image for the deb image): +IMAGE=$(jq -r '.package_configs.rhel[0].image' .github/scripts/strategy-matrix/linux.json) -VERSION=2.4.0-local PKG_RELEASE=1 docker run --rm \ -v "$(pwd):/src" \ -w /src \ - "$IMAGE" \ - ./package/build_pkg.sh --pkg-version "$VERSION" --pkg-release "$PKG_RELEASE" + "${IMAGE}" \ + ./package/build_pkg.sh --pkg-release "${PKG_RELEASE}" # Output: # build/debbuild/*.deb (DEB + dbgsym .ddeb) @@ -91,41 +87,73 @@ needed, but the host toolchain replaces the pinned CI image: ```bash cmake \ -Dxrpld=ON \ - -Dxrpld_version=2.4.0-local \ + -Dpkg_release=1 \ -Dtests=OFF \ .. cmake --build . --target package # deb on Debian/Ubuntu, rpm on RHEL ``` -The `cmake/XrplPackaging.cmake` module defines the target only if at least one -of `rpmbuild` / `dpkg-buildpackage` is present; `build_pkg.sh` then infers the -package format from the host's package manager. The packaging script installs -to FHS-standard paths (`/usr/bin`, `/etc/xrpld`, etc.) regardless of +The `cmake/XrplPackaging.cmake` module defines the `package` target only if at +least one of `rpmbuild` / `dpkg-buildpackage` is present; `build_pkg.sh` then +infers the package format from the host's package manager. The packaging script +installs to FHS-standard paths (`/usr/bin`, `/etc/xrpld`, etc.) regardless of `CMAKE_INSTALL_PREFIX`. +The package version is not a CMake input on this path: `build_pkg.sh` derives it +from the just-built `xrpld` binary's `xrpld --version` output. The package +release defaults to 1 and is overridable with `-Dpkg_release=N`. + ## How `build_pkg.sh` works -`build_pkg.sh` accepts long-form flags, each of which can also be set via an -environment variable. Flags override env vars; env vars override the built-in -defaults. Run `./package/build_pkg.sh --help` for the same table: +`build_pkg.sh` derives the `xrpld` software version from +`${BUILD_DIR}/xrpld --version` in both package formats. -| Flag | Env var | Default | Purpose | -| -------------------------- | ------------------- | ----------------------------- | ----------------------------------- | -| `--src-dir DIR` | `SRC_DIR` | `$PWD` | repo root | -| `--build-dir DIR` | `BUILD_DIR` | `$PWD/build` | directory holding pre-built `xrpld` | -| `--pkg-version STR` | `PKG_VERSION` | parsed from `xrpld --version` | version string, e.g. `3.2.0-b1` | -| `--pkg-release N` | `PKG_RELEASE` | `1` | package release number | -| `--source-date-epoch SECS` | `SOURCE_DATE_EPOCH` | latest git commit ctime | reproducibility timestamp | +The binary's version is already SemVer-validated by `BuildInfo`. +`build_pkg.sh` converts pre-release versions such as `3.2.0-b1` or +`3.2.0-rc1` from `-` to `~` for package metadata so pre-releases sort before +the final release. If that normalized package version still contains `-`, +packaging fails because RPM forbids `-` in `Version`, and Debian uses `-` as +the upstream/revision separator. + +`pkg_version` is the normalized package metadata version derived inside +`build_pkg.sh` from the binary-reported `xrpld` version (`-` pre-release +separator converted to `~`). It is not a separate user input. + +`PKG_RELEASE` is a different value: the package release iteration for that +`xrpld` version. RPM receives the normalized `pkg_version` and `PKG_RELEASE` as +the `pkg_version` and `pkg_release` macros for its `Version` and `Release` +values; DEB writes them as `${pkg_version}-${PKG_RELEASE}` in +`debian/changelog`. + +With `PKG_RELEASE=1`, the package metadata becomes: + +| Input version | RPM version/release | Debian version | +| ------------------ | ---------------------------- | -------------------- | +| `3.2.0` | `3.2.0-1%{?dist}` | `3.2.0-1` | +| `3.2.0-b0+abc1234` | `3.2.0~b0+abc1234-1%{?dist}` | `3.2.0~b0+abc1234-1` | +| `3.2.0-b1` | `3.2.0~b1-1%{?dist}` | `3.2.0~b1-1` | +| `3.2.0-rc1` | `3.2.0~rc1-1%{?dist}` | `3.2.0~rc1-1` | + +The Debian changelog entry carries the repository component: final releases use +`stable`, `b0` builds, including `b0+metadata`, use `develop`, and `bN`/`rcN` +pre-releases use `unstable`. +Build metadata on a final release, such as `3.2.0+abc123`, is rejected. + +The RPM path intentionally uses `~` in `Version`, matching the Debian +pre-release ordering convention, so RPM filenames/NVRs begin with forms like +`xrpld-3.2.0~b1-...` and `xrpld-3.2.0~rc1-...` instead of encoding +pre-releases with an older `0..` RPM `Release` value. The package format (`deb` or `rpm`) is inferred from the host's package manager (`apt-get` -> deb, `dnf`/`yum` -> rpm). Hosts without one of those fail early. Flags are for explicit invocation; environment variables are intended for -CMake/systemd/CI integration. The CI workflow and the CMake `package` target -both invoke `build_pkg.sh` with no flags, configuring it entirely via env -(see `cmake/XrplPackaging.cmake`). +CMake/CI integration. The CI workflow and the CMake `package` target both invoke +`build_pkg.sh` with no flags; CMake supplies `SRC_DIR`, `BUILD_DIR`, and +`PKG_RELEASE` via env, while CI supplies `BUILD_DIR` and `PKG_RELEASE` via env +and lets the script use defaults for the rest. It resolves `SRC_DIR` and `BUILD_DIR` to absolute paths, then calls `stage_common()` to copy the binary, config files, and shared support files @@ -134,18 +162,32 @@ into the staging area, and invokes the platform build tool. ### RPM 1. Creates the standard `rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}` tree inside the build directory. -2. Copies `xrpld.spec` and all source files (binary, configs, service files) into `SOURCES/`. -3. Runs `rpmbuild -bb --define "xrpld_version ..." --define "pkg_release ..."`. The spec uses manual `install` commands to place files. +2. Copies `xrpld.spec` and all shared source files (binary, configs, service files) into `SOURCES/`. +3. Runs `rpmbuild -bb`, passing the normalized package metadata version as the + `pkg_version` RPM macro and `PKG_RELEASE` as the `pkg_release` RPM macro. + The spec uses manual `install` commands to place files, disables `dwz`, and + writes uncompressed RPM payloads while generating debuginfo packages. 4. Output: `rpmbuild/RPMS/x86_64/xrpld-*.rpm` +The uncompressed RPM payload setting is intentionally unconditional for +generated RPMs. It trades larger RPM artifacts for much shorter package +build/validation time, which keeps RPM package validation in the same rough time +class as Debian package validation. + +RPM upgrades intentionally do not restart a running `xrpld` service. The spec +uses `%systemd_postun`, matching Debian's `dh_installsystemd +--no-stop-on-upgrade` behavior; operators pick up the new binary on the next +service restart. + ### DEB 1. Creates a staging source tree at `debbuild/source/` inside the build directory. 2. Stages the binary, configs, `README.md`, and `LICENSE.md`. 3. Copies `package/debian/` control files into `debbuild/source/debian/`. 4. Copies shared service/sysusers/tmpfiles into `debian/` where `dh_installsystemd`, `dh_installsysusers`, and `dh_installtmpfiles` pick them up automatically. -5. Generates a minimal `debian/changelog` (pre-release versions use `~` instead of `-`). -6. Runs `dpkg-buildpackage -b --no-sign`. `debian/rules` uses manual `install` commands. +5. Generates a minimal `debian/changelog` using `${pkg_version}-${PKG_RELEASE}`, + where `pkg_version` is derived from the binary-reported `xrpld` version. +6. Runs `dpkg-buildpackage -b --no-sign -d` (`-d` skips the build-dependency check, since the binary is already built). `debian/rules` uses manual `install` commands. 7. Output: `debbuild/*.deb` and `debbuild/*.ddeb` (dbgsym package) ## Post-build verification @@ -161,11 +203,14 @@ rpm -qlp rpmbuild/RPMS/x86_64/*.rpm ## Reproducibility -The following environment variables improve build reproducibility. They are not -set automatically by `build_pkg.sh`; set them manually if needed: +`build_pkg.sh` already defaults `SOURCE_DATE_EPOCH` to the latest git commit +time, or the current time outside a git tree, and exports it (override with +`--source-date-epoch` / `SOURCE_DATE_EPOCH`); the RPM spec clamps file +modification times to it via `%build_mtime_policy`. The remaining variables +below further improve reproducibility but are _not_ set by the script — export +them yourself if needed: ```bash -export SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct) export TZ=UTC export LC_ALL=C.UTF-8 export GZIP=-n diff --git a/package/build_pkg.sh b/package/build_pkg.sh index e2ec8fee3d..3684fc096a 100755 --- a/package/build_pkg.sh +++ b/package/build_pkg.sh @@ -3,20 +3,18 @@ set -euo pipefail # Build an RPM or Debian package from a pre-built xrpld binary. # -# Flags override env vars; env vars override defaults. Env vars are intended -# for CMake/systemd/CI integration; flags are for explicit invocation. +# Flags override env vars; env vars override defaults. usage() { cat <<'EOF' Usage: build_pkg.sh [options] Options (each can also be set via the env var shown): - --src-dir DIR repo root [SRC_DIR; default: $PWD] - --build-dir DIR directory holding xrpld [BUILD_DIR; default: $PWD/build] - --pkg-version STR version, e.g. 3.2.0-b1 [PKG_VERSION; default: parsed from xrpld --version] - --pkg-release N package release number [PKG_RELEASE; default: 1] - --source-date-epoch SECS reproducibility timestamp [SOURCE_DATE_EPOCH; default: latest git commit ctime] - -h, --help show this help and exit + --src-dir DIR repo root [SRC_DIR; default: ${PWD}] + --build-dir DIR directory holding xrpld [BUILD_DIR; default: ${PWD}/build] + --pkg-release N package release iteration [PKG_RELEASE; default: 1] + --source-date-epoch SECS reproducibility timestamp [SOURCE_DATE_EPOCH; latest git ctime; fallback: current time] + -h, --help show this help and exit EOF } @@ -30,8 +28,7 @@ need_arg() { # Seed from env. CLI parsing below overrides these directly. SRC_DIR="${SRC_DIR:-}" BUILD_DIR="${BUILD_DIR:-}" -PKG_VERSION="${PKG_VERSION:-}" -PKG_RELEASE="${PKG_RELEASE:-}" +PKG_RELEASE="${PKG_RELEASE:-1}" SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:-}" while [[ $# -gt 0 ]]; do @@ -46,11 +43,6 @@ while [[ $# -gt 0 ]]; do BUILD_DIR="$2" shift 2 ;; - --pkg-version) - need_arg "$@" - PKG_VERSION="$2" - shift 2 - ;; --pkg-release) need_arg "$@" PKG_RELEASE="$2" @@ -74,19 +66,61 @@ while [[ $# -gt 0 ]]; do done SRC_DIR="$(cd "${SRC_DIR:-${PWD}}" && pwd)" -BUILD_DIR="$(cd "${BUILD_DIR:-${PWD}/build}" && pwd)" -PKG_RELEASE="${PKG_RELEASE:-1}" - -if [[ -z "${PKG_VERSION}" ]]; then - PKG_VERSION="$("${BUILD_DIR}/xrpld" --version | awk 'NR==1 {print $3; exit}')" +BUILD_DIR="${BUILD_DIR:-${PWD}/build}" +if [[ ! -d "${BUILD_DIR}" ]]; then + echo "build_pkg.sh: build directory not found: ${BUILD_DIR}" >&2 + echo "Build xrpld before packaging, or set BUILD_DIR to the directory containing xrpld." >&2 + exit 1 fi +BUILD_DIR="$(cd "${BUILD_DIR}" && pwd)" -if [[ -z "${PKG_VERSION}" ]]; then - echo "PKG_VERSION is empty (not provided and could not be derived)." >&2 +xrpld_binary="${BUILD_DIR}/xrpld" +if [[ ! -x "${xrpld_binary}" ]]; then + echo "build_pkg.sh: expected executable xrpld binary at ${xrpld_binary}." >&2 + echo "Build xrpld before packaging, or set BUILD_DIR to the directory containing xrpld." >&2 exit 1 fi -VERSION="${PKG_VERSION}" +xrpld_version="$("${xrpld_binary}" --version | awk 'NR == 1 { print $3 }')" + +if [[ -z "${xrpld_version}" ]]; then + echo "build_pkg.sh: unable to derive xrpld version from ${xrpld_binary} --version." >&2 + exit 1 +fi + +# The version as the package formats consume it: identical to xrpld_version +# except a pre-release uses '~' (3.2.0-b1 -> 3.2.0~b1), which also sorts before +# the final 3.2.0; a no-op for a final release. Lowercase = derived internally, +# not an input (cf. pkg_type). +pkg_version="${xrpld_version}" +pre_release="" +if [[ "${xrpld_version}" == *-* ]]; then + pre_release="${xrpld_version#*-}" + pkg_version="${xrpld_version%%-*}~${pre_release}" +fi + +# BuildInfo already SemVer-validates the binary's version. Packaging adds one +# narrower constraint: after pre-release normalization, the package version must +# not contain '-' because RPM forbids it in Version and Debian uses it as the +# upstream/revision separator. +if [[ "${pkg_version}" == *-* ]]; then + echo "build_pkg.sh: unsupported xrpld version '${xrpld_version}'." >&2 + echo "Package version '${pkg_version}' cannot contain '-'." >&2 + echo "Use a single-token pre-release like 3.2.0-b1 or 3.2.0-rc2." >&2 + exit 1 +fi + +if [[ -z "${pre_release}" && "${xrpld_version}" == *+* ]]; then + echo "build_pkg.sh: unsupported xrpld version '${xrpld_version}'." >&2 + echo "Build metadata is only supported on bN/rcN pre-releases." >&2 + exit 1 +fi + +if [[ -n "${pre_release}" && ! "${pre_release}" =~ ^(b0|b[1-9][0-9]*|rc[0-9]+)(\+.*)?$ ]]; then + echo "build_pkg.sh: unsupported xrpld pre-release '${pre_release}'." >&2 + echo "Use bN or rcN, e.g. 3.2.0-b1 or 3.2.0-rc2." >&2 + exit 1 +fi if command -v apt-get >/dev/null 2>&1; then pkg_type=deb @@ -98,32 +132,15 @@ else fi if [[ -z "${SOURCE_DATE_EPOCH}" ]]; then - if git -C "$SRC_DIR" rev-parse --is-inside-work-tree >/dev/null 2>&1; then - SOURCE_DATE_EPOCH="$(git -C "$SRC_DIR" log -1 --format=%ct)" + if git -C "${SRC_DIR}" rev-parse --is-inside-work-tree >/dev/null 2>&1; then + SOURCE_DATE_EPOCH="$(git -C "${SRC_DIR}" log -1 --format=%ct)" else SOURCE_DATE_EPOCH="$(date +%s)" fi fi export SOURCE_DATE_EPOCH -CHANGELOG_DATE="$(date -u -R -d "@$SOURCE_DATE_EPOCH")" - -# Split VERSION at the first '-' into base and optional pre-release suffix. -# Examples: "3.2.0" -> ("3.2.0", ""); "3.2.0-b1" -> ("3.2.0", "b1"). -VER_BASE="${VERSION%%-*}" -VER_SUFFIX="${VERSION#*-}" -[[ "${VER_SUFFIX}" == "${VERSION}" ]] && VER_SUFFIX="" - -# Reject multi-segment suffixes (e.g. "beta-1", "rc1-15-gabc123"). Neither an -# RPM Version nor a Debian upstream version may contain '-' (it's the NVR / -# version-revision separator), and the convention here is single-token -# suffixes like b1 or rc2. Fail early with a clear message rather than letting -# the package tooling blow up or silently mangle dashes. -if [[ "${VER_SUFFIX}" == *-* ]]; then - echo "build_pkg.sh: multi-segment pre-release in VERSION='${VERSION}' (suffix '${VER_SUFFIX}')." >&2 - echo "Use single-token suffixes like 3.2.0-b1 or 3.2.0-rc2." >&2 - exit 1 -fi +CHANGELOG_DATE="$(date -u -R -d "@${SOURCE_DATE_EPOCH}")" SHARED="${SRC_DIR}/package/shared" DEBIAN_DIR="${SRC_DIR}/package/debian" @@ -143,7 +160,6 @@ stage_common() { cp "${SHARED}/xrpld.sysusers" "${dest}/xrpld.sysusers" cp "${SHARED}/xrpld.tmpfiles" "${dest}/xrpld.tmpfiles" cp "${SHARED}/xrpld.logrotate" "${dest}/xrpld.logrotate" - cp "${SHARED}/50-xrpld.preset" "${dest}/50-xrpld.preset" } build_rpm() { @@ -154,18 +170,11 @@ build_rpm() { cp "${SRC_DIR}/package/rpm/xrpld.spec" "${topdir}/SPECS/xrpld.spec" stage_common "${topdir}/SOURCES" - # Pre-releases use the modern rpm '~' convention (rpm >= 4.10): the suffix - # goes in Version (e.g. 3.2.0~b1), which rpmvercmp sorts *before* the final - # 3.2.0 — identical semantics to Debian's '~'. Release is just the package - # release number. This replaces the older "0.." Release - # hack and keeps the RPM and DEB version strings symmetric. - local rpm_version="${VER_BASE}${VER_SUFFIX:+~${VER_SUFFIX}}" - set -x rpmbuild -bb \ --define "_topdir ${topdir}" \ - --define "xrpld_version ${rpm_version}" \ - --define "xrpld_release ${PKG_RELEASE}" \ + --define "pkg_version ${pkg_version}" \ + --define "pkg_release ${PKG_RELEASE}" \ "${topdir}/SPECS/xrpld.spec" } @@ -182,23 +191,26 @@ build_deb() { cp "${staging}/xrpld.tmpfiles" "${staging}/debian/xrpld.tmpfiles" cp "${staging}/xrpld.logrotate" "${staging}/debian/xrpld.logrotate" - # Debian '~' marks a pre-release; 3.2.0~b1 sorts before 3.2.0. - local deb_full_version="${VER_BASE}${VER_SUFFIX:+~${VER_SUFFIX}}-${PKG_RELEASE}" - - # Derive release channel from the version suffix: - # (none) -> stable (tagged release) - # b0 -> develop (develop-branch build) - # b, rc -> unstable (pre-release) - local deb_distribution - case "${VER_SUFFIX}" in - "") deb_distribution="stable" ;; - b0) deb_distribution="develop" ;; - *) deb_distribution="unstable" ;; - esac + # Choose the Debian repository component for this package. + # 3.2.0 -> stable, *-b0[+metadata] -> develop, + # bN/rcN pre-releases -> unstable. + local deb_component + if [[ -z "${pre_release}" ]]; then + deb_component="stable" + elif [[ "${pre_release}" =~ ^b0(\+.*)?$ ]]; then + deb_component="develop" + elif [[ "${pre_release}" =~ ^(b[1-9][0-9]*|rc[0-9]+)(\+.*)?$ ]]; then + deb_component="unstable" + else + echo "build_pkg.sh: unsupported xrpld pre-release '${pre_release}'." >&2 + echo "Use bN or rcN, e.g. 3.2.0-b1 or 3.2.0-rc2." >&2 + exit 1 + fi + # Debian version is [~
]-.
     cat >"${staging}/debian/changelog" <  ${CHANGELOG_DATE}
 EOF
diff --git a/package/rpm/xrpld.spec b/package/rpm/xrpld.spec
index 5595fd0d8d..61c2d61ec6 100644
--- a/package/rpm/xrpld.spec
+++ b/package/rpm/xrpld.spec
@@ -1,6 +1,14 @@
+%if "%{?pkg_version}" == ""
+%{error:pkg_version must be defined}
+%endif
+
+%if "%{?pkg_release}" == ""
+%{error:pkg_release must be defined}
+%endif
+
 Name:     xrpld
-Version:  %{xrpld_version}
-Release:  %{xrpld_release}%{?dist}
+Version:  %{pkg_version}
+Release:  %{pkg_release}%{?dist}
 Summary:  XRP Ledger daemon
 
 License:  ISC
@@ -11,6 +19,9 @@ BuildRequires: systemd-rpm-macros
 
 %undefine _debugsource_packages
 %debug_package
+# Intentionally trade larger RPM artifacts for faster package validation.
+%global _binary_payload w.ufdio
+%global _find_debuginfo_dwz_opts %{nil}
 
 %build_mtime_policy clamp_to_source_date_epoch
 
@@ -37,7 +48,10 @@ install -Dm0644 %{_sourcedir}/validators.txt       %{buildroot}%{_sysconfdir}/%{
 install -Dm0644 %{_sourcedir}/xrpld.service        %{buildroot}%{_unitdir}/xrpld.service
 install -Dm0644 %{_sourcedir}/xrpld.sysusers       %{buildroot}%{_sysusersdir}/xrpld.conf
 install -Dm0644 %{_sourcedir}/xrpld.tmpfiles       %{buildroot}%{_tmpfilesdir}/xrpld.conf
-install -Dm0644 %{_sourcedir}/50-xrpld.preset      %{buildroot}%{_presetdir}/50-xrpld.preset
+install -Dm0644 /dev/null %{buildroot}%{_presetdir}/50-xrpld.preset
+cat >%{buildroot}%{_presetdir}/50-xrpld.preset <<'EOF'
+enable xrpld.service
+EOF
 
 # Logrotate config
 install -Dm0644 %{_sourcedir}/xrpld.logrotate      %{buildroot}%{_sysconfdir}/logrotate.d/%{name}
@@ -62,7 +76,7 @@ systemd-tmpfiles --create %{_tmpfilesdir}/xrpld.conf || :
 %systemd_preun xrpld.service
 
 %postun
-%systemd_postun_with_restart xrpld.service
+%systemd_postun xrpld.service
 
 %files
 %license %{_docdir}/%{name}/LICENSE.md
diff --git a/package/shared/50-xrpld.preset b/package/shared/50-xrpld.preset
deleted file mode 100644
index bfbcd56577..0000000000
--- a/package/shared/50-xrpld.preset
+++ /dev/null
@@ -1,2 +0,0 @@
-# /usr/lib/systemd/system-preset/50-xrpld.preset
-enable xrpld.service

From 3097c157b6ca13d368eef8b03d26fa027b277a4c Mon Sep 17 00:00:00 2001
From: Ayaz Salikhov 
Date: Thu, 25 Jun 2026 13:40:06 +0100
Subject: [PATCH 13/14] build: Switch to a new conan XRPLF remote (#7622)

---
 .github/actions/setup-conan/action.yml       |  2 +-
 .github/workflows/on-pr.yml                  |  4 +-
 .github/workflows/on-tag.yml                 |  4 +-
 .github/workflows/on-trigger.yml             |  4 +-
 .github/workflows/reusable-upload-recipe.yml | 20 ++----
 .github/workflows/upload-conan-deps.yml      |  6 +-
 BUILD.md                                     |  2 +-
 conan.lock                                   | 64 ++++++++++----------
 conan/lockfile/regenerate.sh                 |  2 +-
 conanfile.py                                 |  4 +-
 docs/build/advanced_conan.md                 |  2 +-
 11 files changed, 54 insertions(+), 60 deletions(-)

diff --git a/.github/actions/setup-conan/action.yml b/.github/actions/setup-conan/action.yml
index 0dd22f0d92..e8a548cfce 100644
--- a/.github/actions/setup-conan/action.yml
+++ b/.github/actions/setup-conan/action.yml
@@ -9,7 +9,7 @@ inputs:
   remote_url:
     description: "The URL of the Conan endpoint to use."
     required: false
-    default: https://conan.ripplex.io
+    default: https://conan.xrplf.org/repository/conan/
 
 runs:
   using: composite
diff --git a/.github/workflows/on-pr.yml b/.github/workflows/on-pr.yml
index 0c9eeda712..2ad0641863 100644
--- a/.github/workflows/on-pr.yml
+++ b/.github/workflows/on-pr.yml
@@ -154,8 +154,8 @@ jobs:
     if: ${{ github.repository == 'XRPLF/rippled' && needs.should-run.outputs.go == 'true' && github.event_name == 'pull_request' && startsWith(github.event.pull_request.base.ref, 'release') }}
     uses: ./.github/workflows/reusable-upload-recipe.yml
     secrets:
-      remote_username: ${{ secrets.CONAN_REMOTE_USERNAME }}
-      remote_password: ${{ secrets.CONAN_REMOTE_PASSWORD }}
+      remote_username: ${{ secrets.NEXUS_REMOTE_USERNAME }}
+      remote_password: ${{ secrets.NEXUS_REMOTE_PASSWORD }}
 
   notify-clio:
     needs: upload-recipe
diff --git a/.github/workflows/on-tag.yml b/.github/workflows/on-tag.yml
index 42d5827cab..abedc13d69 100644
--- a/.github/workflows/on-tag.yml
+++ b/.github/workflows/on-tag.yml
@@ -20,8 +20,8 @@ jobs:
     if: ${{ github.repository == 'XRPLF/rippled' }}
     uses: ./.github/workflows/reusable-upload-recipe.yml
     secrets:
-      remote_username: ${{ secrets.CONAN_REMOTE_USERNAME }}
-      remote_password: ${{ secrets.CONAN_REMOTE_PASSWORD }}
+      remote_username: ${{ secrets.NEXUS_REMOTE_USERNAME }}
+      remote_password: ${{ secrets.NEXUS_REMOTE_PASSWORD }}
 
   build-test:
     if: ${{ github.repository == 'XRPLF/rippled' }}
diff --git a/.github/workflows/on-trigger.yml b/.github/workflows/on-trigger.yml
index 063cdbff7f..5f018cb12c 100644
--- a/.github/workflows/on-trigger.yml
+++ b/.github/workflows/on-trigger.yml
@@ -98,8 +98,8 @@ jobs:
     if: ${{ github.repository == 'XRPLF/rippled' && github.event_name == 'push' && github.ref == 'refs/heads/develop' }}
     uses: ./.github/workflows/reusable-upload-recipe.yml
     secrets:
-      remote_username: ${{ secrets.CONAN_REMOTE_USERNAME }}
-      remote_password: ${{ secrets.CONAN_REMOTE_PASSWORD }}
+      remote_username: ${{ secrets.NEXUS_REMOTE_USERNAME }}
+      remote_password: ${{ secrets.NEXUS_REMOTE_PASSWORD }}
 
   package:
     needs: build-test
diff --git a/.github/workflows/reusable-upload-recipe.yml b/.github/workflows/reusable-upload-recipe.yml
index a18f76796a..feeee0a621 100644
--- a/.github/workflows/reusable-upload-recipe.yml
+++ b/.github/workflows/reusable-upload-recipe.yml
@@ -14,7 +14,7 @@ on:
         description: "The URL of the Conan endpoint to use."
         required: false
         type: string
-        default: https://conan.ripplex.io
+        default: https://conan.xrplf.org/repository/conan/
 
     secrets:
       remote_username:
@@ -41,6 +41,10 @@ jobs:
   upload:
     runs-on: ubuntu-latest
     container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-e29b523
+    env:
+      REMOTE_NAME: ${{ inputs.remote_name }}
+      CONAN_LOGIN_USERNAME_XRPLF: ${{ secrets.remote_username }}
+      CONAN_PASSWORD_XRPLF: ${{ secrets.remote_password }}
     steps:
       - name: Checkout repository
         uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
@@ -56,15 +60,9 @@ jobs:
           remote_url: ${{ inputs.remote_url }}
 
       - name: Log into Conan remote
-        env:
-          REMOTE_NAME: ${{ inputs.remote_name }}
-          REMOTE_USERNAME: ${{ secrets.remote_username }}
-          REMOTE_PASSWORD: ${{ secrets.remote_password }}
-        run: conan remote login "${REMOTE_NAME}" "${REMOTE_USERNAME}" --password "${REMOTE_PASSWORD}"
+        run: conan remote login "${REMOTE_NAME}" "${CONAN_LOGIN_USERNAME_XRPLF}" --password "${CONAN_PASSWORD_XRPLF}"
 
       - name: Upload Conan recipe (version)
-        env:
-          REMOTE_NAME: ${{ inputs.remote_name }}
         run: |
           conan export . --version=${{ steps.version.outputs.version }}
           conan upload --confirm --check --remote="${REMOTE_NAME}" xrpl/${{ steps.version.outputs.version }}
@@ -73,8 +71,6 @@ jobs:
       # 'develop' branch, see on-trigger.yml.
       - name: Upload Conan recipe (develop)
         if: ${{ github.event_name == 'push' }}
-        env:
-          REMOTE_NAME: ${{ inputs.remote_name }}
         run: |
           conan export . --version=develop
           conan upload --confirm --check --remote="${REMOTE_NAME}" xrpl/develop
@@ -83,8 +79,6 @@ jobs:
       # one of the 'release' branches, see on-pr.yml.
       - name: Upload Conan recipe (rc)
         if: ${{ github.event_name == 'pull_request' }}
-        env:
-          REMOTE_NAME: ${{ inputs.remote_name }}
         run: |
           conan export . --version=rc
           conan upload --confirm --check --remote="${REMOTE_NAME}" xrpl/rc
@@ -93,8 +87,6 @@ jobs:
       # release, see on-tag.yml.
       - name: Upload Conan recipe (release)
         if: ${{ startsWith(github.ref, 'refs/tags/') }}
-        env:
-          REMOTE_NAME: ${{ inputs.remote_name }}
         run: |
           conan export . --version=release
           conan upload --confirm --check --remote="${REMOTE_NAME}" xrpl/release
diff --git a/.github/workflows/upload-conan-deps.yml b/.github/workflows/upload-conan-deps.yml
index 5d3712cf9e..92b72cf6a9 100644
--- a/.github/workflows/upload-conan-deps.yml
+++ b/.github/workflows/upload-conan-deps.yml
@@ -34,7 +34,7 @@ on:
 
 env:
   CONAN_REMOTE_NAME: xrplf
-  CONAN_REMOTE_URL: https://conan.ripplex.io
+  CONAN_REMOTE_URL: https://conan.xrplf.org/repository/conan/
   NPROC_SUBTRACT: 2
 
 concurrency:
@@ -108,10 +108,12 @@ jobs:
 
       - name: Log into Conan remote
         if: ${{ github.repository == 'XRPLF/rippled' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') }}
-        run: conan remote login "${CONAN_REMOTE_NAME}" "${{ secrets.CONAN_REMOTE_USERNAME }}" --password "${{ secrets.CONAN_REMOTE_PASSWORD }}"
+        run: conan remote login "${CONAN_REMOTE_NAME}" "${{ secrets.NEXUS_REMOTE_USERNAME }}" --password "${{ secrets.NEXUS_REMOTE_PASSWORD }}"
 
       - name: Upload Conan packages
         if: ${{ github.repository == 'XRPLF/rippled' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') }}
         env:
           FORCE_OPTION: ${{ github.event.inputs.force_upload == 'true' && '--force' || '' }}
+          CONAN_LOGIN_USERNAME_XRPLF: ${{ secrets.NEXUS_REMOTE_USERNAME }}
+          CONAN_PASSWORD_XRPLF: ${{ secrets.NEXUS_REMOTE_PASSWORD }}
         run: conan upload "*" --remote="${CONAN_REMOTE_NAME}" --confirm ${FORCE_OPTION}
diff --git a/BUILD.md b/BUILD.md
index 2ac24f2c5d..847cd7bc1a 100644
--- a/BUILD.md
+++ b/BUILD.md
@@ -101,7 +101,7 @@ More information on customizing Conan can be found in the [Advanced Conan config
 Run the following command to add the `xrplf` remote, which hosts some of our dependencies:
 
 ```bash
-conan remote add --index 0 --force xrplf https://conan.ripplex.io
+conan remote add --index 0 --force xrplf https://conan.xrplf.org/repository/conan/
 ```
 
 ### Set Up Ccache
diff --git a/conan.lock b/conan.lock
index d80a6d0c57..ae45a900b6 100644
--- a/conan.lock
+++ b/conan.lock
@@ -1,43 +1,43 @@
 {
     "version": "0.5",
     "requires": [
-        "zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1778091116.056",
-        "xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1765850149.987",
-        "sqlite3/3.53.0#324ada52333108388a9a6108bfa96734%1778091117.311",
-        "soci/4.0.3#fe32b9ad5eb47e79ab9e45a68f363945%1774450067.231",
-        "snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1765850147.878",
-        "secp256k1/0.7.1#481881709eb0bdd0185a12b912bbe8ad%1770910500.329",
-        "rocksdb/10.5.1#4a197eca381a3e5ae8adf8cffa5aacd0%1765850186.86",
-        "re2/20251105#8579cfd0bda4daf0683f9e3898f964b4%1774398111.888",
-        "protobuf/6.33.5#d96d52ba5baaaa532f47bda866ad87a5%1774467363.12",
-        "openssl/3.6.2#4789bbf131b77d0515d15e094c8f697f%1778071755.506",
-        "nudb/2.0.9#11149c73f8f2baff9a0198fe25971fc7%1775040983.408",
-        "lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1765850143.914",
-        "libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1765842973.492",
-        "libbacktrace/cci.20210118#a7691bfccd8caaf66309df196790a5a1%1765842973.03",
-        "libarchive/3.8.7#c446109bd1f1d8ba7936c94189bc50e6%1778091117.848",
+        "zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1777558780.503",
+        "xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1743678659.187",
+        "sqlite3/3.53.0#324ada52333108388a9a6108bfa96734%1776096494.149",
+        "soci/4.0.3#e726491a03468795453f7c83fc924a96%1751554127.172",
+        "snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1782307151.633168",
+        "secp256k1/0.7.1#b1f450b7f78a36fff75bb6934a356f3a%1782338841.3729",
+        "rocksdb/10.5.1#4a197eca381a3e5ae8adf8cffa5aacd0%1759820024.194",
+        "re2/20251105#8579cfd0bda4daf0683f9e3898f964b4%1772560729.95",
+        "protobuf/6.33.5#ff253ead763bd8d9904a52979cd21e81%1778763145.334",
+        "openssl/3.6.3#1163d4ddc603907084d08a6a0c6e580f%1782307150.583886",
+        "nudb/2.0.9#11149c73f8f2baff9a0198fe25971fc7%1774883011.384",
+        "lz4/1.10.0#982d9b673900f665a1da109e09c17cab%1775037240.923",
+        "libiconv/1.17#9923bc6dc6f106646d6967e0039a5ada%1774021608.288",
+        "libbacktrace/cci.20210118#a7691bfccd8caaf66309df196790a5a1%1722218217.276",
+        "libarchive/3.8.7#c446109bd1f1d8ba7936c94189bc50e6%1776147552.838",
         "jemalloc/5.3.1#1fc58d55316041f10fbc1e8a2eae632a%1776700028.228",
-        "gtest/1.17.0#5224b3b3ff3b4ce1133cbdd27d53ee7d%1768312129.152",
-        "grpc/1.81.0#2fb144aeb47e7f35c6ebb0e5f35bed31%1781620605.685",
-        "ed25519/2015.03#ae761bdc52730a843f0809bdf6c1b1f6%1765850143.772",
-        "date/3.0.4#862e11e80030356b53c2c38599ceb32b%1765850143.772",
-        "c-ares/1.34.6#545240bb1c40e2cacd4362d6b8967650%1774439234.681",
-        "bzip2/1.0.8#c470882369c2d95c5c77e970c0c7e321%1765850143.837",
-        "boost/1.91.0#ea540ca2133d831b560036aa24dece3c%1778091165.282",
-        "abseil/20250127.0#bb0baf1f362bc4a725a24eddd419b8f7%1774365460.196"
+        "gtest/1.17.0#5224b3b3ff3b4ce1133cbdd27d53ee7d%1755784855.585",
+        "grpc/1.81.1#5217e6ef0544c42b46f4af35d5e7f649%1782307148.845616",
+        "ed25519/2015.03#ae761bdc52730a843f0809bdf6c1b1f6%1782307148.15562",
+        "date/3.0.4#862e11e80030356b53c2c38599ceb32b%1754573467.979",
+        "c-ares/1.34.6#545240bb1c40e2cacd4362d6b8967650%1766500685.317",
+        "bzip2/1.0.8#c470882369c2d95c5c77e970c0c7e321%1762886692.465",
+        "boost/1.91.0#ea540ca2133d831b560036aa24dece3c%1778050991.9",
+        "abseil/20250127.0#bb0baf1f362bc4a725a24eddd419b8f7%1782307147.395833"
     ],
     "build_requires": [
-        "zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1778091116.056",
-        "strawberryperl/5.32.1.1#8d114504d172cfea8ea1662d09b6333e%1774447376.964",
-        "protobuf/6.33.5#d96d52ba5baaaa532f47bda866ad87a5%1774467363.12",
-        "nasm/2.16.01#31e26f2ee3c4346ecd347911bd126904%1765850144.707",
+        "zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1777558780.503",
+        "strawberryperl/5.32.1.1#8d114504d172cfea8ea1662d09b6333e%1751971032.423",
+        "protobuf/6.33.5#ff253ead763bd8d9904a52979cd21e81%1778763145.334",
+        "nasm/2.16.01#31e26f2ee3c4346ecd347911bd126904%1745483323.489",
         "msys2/cci.latest#d22fe7b2808f5fd34d0a7923ace9c54f%1770657326.649",
-        "m4/1.4.19#4523e4347b55cd26ae918bd5770cab9a%1778062762.471",
-        "cmake/4.3.0#b939a42e98f593fb34d3a8c5cc860359%1774439249.183",
-        "b2/5.4.2#ffd6084a119587e70f11cd45d1a386e2%1774439233.447",
+        "m4/1.4.19#34c4bbc3eeebe98ca6edf2f52d602e7d%1777282960.259",
+        "cmake/4.3.3#840cf00ea09777e05c2050a50a82c722%1781521538.233",
+        "b2/5.4.2#ffd6084a119587e70f11cd45d1a386e2%1766594659.866",
         "automake/1.16.5#b91b7c384c3deaa9d535be02da14d04f%1755524470.56",
         "autoconf/2.71#51077f068e61700d65bb05541ea1e4b0%1731054366.86",
-        "abseil/20250127.0#bb0baf1f362bc4a725a24eddd419b8f7%1774365460.196"
+        "abseil/20250127.0#bb0baf1f362bc4a725a24eddd419b8f7%1782307147.395833"
     ],
     "python_requires": [],
     "overrides": {
@@ -57,7 +57,7 @@
             "boost/1.91.0"
         ],
         "lz4/[>=1.9.4 <2]": [
-            "lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504"
+            "lz4/1.10.0#982d9b673900f665a1da109e09c17cab"
         ]
     },
     "config_requires": []
diff --git a/conan/lockfile/regenerate.sh b/conan/lockfile/regenerate.sh
index 1aa47628f0..98ee6f7c99 100755
--- a/conan/lockfile/regenerate.sh
+++ b/conan/lockfile/regenerate.sh
@@ -14,7 +14,7 @@ export CONAN_HOME="$TEMP_DIR"
 # Ensure that the xrplf remote is the first to be consulted, so any recipes we
 # patched are used. We also add it there to not created huge diff when the
 # official Conan Center Index is updated.
-conan remote add --force --index 0 xrplf https://conan.ripplex.io
+conan remote add --force --index 0 xrplf https://conan.xrplf.org/repository/conan/
 
 # Delete any existing lockfile.
 rm -f conan.lock
diff --git a/conanfile.py b/conanfile.py
index 5b78dc22e3..2733d4fc9c 100644
--- a/conanfile.py
+++ b/conanfile.py
@@ -28,10 +28,10 @@ class Xrpl(ConanFile):
 
     requires = [
         "ed25519/2015.03",
-        "grpc/1.81.0",
+        "grpc/1.81.1",
         "libarchive/3.8.7",
         "nudb/2.0.9",
-        "openssl/3.6.2",
+        "openssl/3.6.3",
         "secp256k1/0.7.1",
         "soci/4.0.3",
         "zlib/1.3.2",
diff --git a/docs/build/advanced_conan.md b/docs/build/advanced_conan.md
index aae17e385a..26b88ef186 100644
--- a/docs/build/advanced_conan.md
+++ b/docs/build/advanced_conan.md
@@ -34,7 +34,7 @@ higher index than the default Conan Center remote, so it is consulted first. You
 can do this by running:
 
 ```bash
-conan remote add --index 0 --force xrplf https://conan.ripplex.io
+conan remote add --index 0 --force xrplf https://conan.xrplf.org/repository/conan/
 ```
 
 Alternatively, you can pull our recipes from the repository and export them locally:

From 07c64f07f02cedf9eeb185fc7c28e2d6711fc113 Mon Sep 17 00:00:00 2001
From: Ayaz Salikhov 
Date: Thu, 25 Jun 2026 15:47:55 +0100
Subject: [PATCH 14/14] chore: Revert "build: Switch to a new conan XRPLF
 remote (#7622)" (#7623)

---
 .github/actions/setup-conan/action.yml       |  2 +-
 .github/workflows/on-pr.yml                  |  4 +-
 .github/workflows/on-tag.yml                 |  4 +-
 .github/workflows/on-trigger.yml             |  4 +-
 .github/workflows/reusable-upload-recipe.yml | 20 ++++--
 .github/workflows/upload-conan-deps.yml      |  6 +-
 BUILD.md                                     |  2 +-
 conan.lock                                   | 64 ++++++++++----------
 conan/lockfile/regenerate.sh                 |  2 +-
 conanfile.py                                 |  4 +-
 docs/build/advanced_conan.md                 |  2 +-
 11 files changed, 60 insertions(+), 54 deletions(-)

diff --git a/.github/actions/setup-conan/action.yml b/.github/actions/setup-conan/action.yml
index e8a548cfce..0dd22f0d92 100644
--- a/.github/actions/setup-conan/action.yml
+++ b/.github/actions/setup-conan/action.yml
@@ -9,7 +9,7 @@ inputs:
   remote_url:
     description: "The URL of the Conan endpoint to use."
     required: false
-    default: https://conan.xrplf.org/repository/conan/
+    default: https://conan.ripplex.io
 
 runs:
   using: composite
diff --git a/.github/workflows/on-pr.yml b/.github/workflows/on-pr.yml
index 2ad0641863..0c9eeda712 100644
--- a/.github/workflows/on-pr.yml
+++ b/.github/workflows/on-pr.yml
@@ -154,8 +154,8 @@ jobs:
     if: ${{ github.repository == 'XRPLF/rippled' && needs.should-run.outputs.go == 'true' && github.event_name == 'pull_request' && startsWith(github.event.pull_request.base.ref, 'release') }}
     uses: ./.github/workflows/reusable-upload-recipe.yml
     secrets:
-      remote_username: ${{ secrets.NEXUS_REMOTE_USERNAME }}
-      remote_password: ${{ secrets.NEXUS_REMOTE_PASSWORD }}
+      remote_username: ${{ secrets.CONAN_REMOTE_USERNAME }}
+      remote_password: ${{ secrets.CONAN_REMOTE_PASSWORD }}
 
   notify-clio:
     needs: upload-recipe
diff --git a/.github/workflows/on-tag.yml b/.github/workflows/on-tag.yml
index abedc13d69..42d5827cab 100644
--- a/.github/workflows/on-tag.yml
+++ b/.github/workflows/on-tag.yml
@@ -20,8 +20,8 @@ jobs:
     if: ${{ github.repository == 'XRPLF/rippled' }}
     uses: ./.github/workflows/reusable-upload-recipe.yml
     secrets:
-      remote_username: ${{ secrets.NEXUS_REMOTE_USERNAME }}
-      remote_password: ${{ secrets.NEXUS_REMOTE_PASSWORD }}
+      remote_username: ${{ secrets.CONAN_REMOTE_USERNAME }}
+      remote_password: ${{ secrets.CONAN_REMOTE_PASSWORD }}
 
   build-test:
     if: ${{ github.repository == 'XRPLF/rippled' }}
diff --git a/.github/workflows/on-trigger.yml b/.github/workflows/on-trigger.yml
index 5f018cb12c..063cdbff7f 100644
--- a/.github/workflows/on-trigger.yml
+++ b/.github/workflows/on-trigger.yml
@@ -98,8 +98,8 @@ jobs:
     if: ${{ github.repository == 'XRPLF/rippled' && github.event_name == 'push' && github.ref == 'refs/heads/develop' }}
     uses: ./.github/workflows/reusable-upload-recipe.yml
     secrets:
-      remote_username: ${{ secrets.NEXUS_REMOTE_USERNAME }}
-      remote_password: ${{ secrets.NEXUS_REMOTE_PASSWORD }}
+      remote_username: ${{ secrets.CONAN_REMOTE_USERNAME }}
+      remote_password: ${{ secrets.CONAN_REMOTE_PASSWORD }}
 
   package:
     needs: build-test
diff --git a/.github/workflows/reusable-upload-recipe.yml b/.github/workflows/reusable-upload-recipe.yml
index feeee0a621..a18f76796a 100644
--- a/.github/workflows/reusable-upload-recipe.yml
+++ b/.github/workflows/reusable-upload-recipe.yml
@@ -14,7 +14,7 @@ on:
         description: "The URL of the Conan endpoint to use."
         required: false
         type: string
-        default: https://conan.xrplf.org/repository/conan/
+        default: https://conan.ripplex.io
 
     secrets:
       remote_username:
@@ -41,10 +41,6 @@ jobs:
   upload:
     runs-on: ubuntu-latest
     container: ghcr.io/xrplf/xrpld/nix-ubuntu:sha-e29b523
-    env:
-      REMOTE_NAME: ${{ inputs.remote_name }}
-      CONAN_LOGIN_USERNAME_XRPLF: ${{ secrets.remote_username }}
-      CONAN_PASSWORD_XRPLF: ${{ secrets.remote_password }}
     steps:
       - name: Checkout repository
         uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
@@ -60,9 +56,15 @@ jobs:
           remote_url: ${{ inputs.remote_url }}
 
       - name: Log into Conan remote
-        run: conan remote login "${REMOTE_NAME}" "${CONAN_LOGIN_USERNAME_XRPLF}" --password "${CONAN_PASSWORD_XRPLF}"
+        env:
+          REMOTE_NAME: ${{ inputs.remote_name }}
+          REMOTE_USERNAME: ${{ secrets.remote_username }}
+          REMOTE_PASSWORD: ${{ secrets.remote_password }}
+        run: conan remote login "${REMOTE_NAME}" "${REMOTE_USERNAME}" --password "${REMOTE_PASSWORD}"
 
       - name: Upload Conan recipe (version)
+        env:
+          REMOTE_NAME: ${{ inputs.remote_name }}
         run: |
           conan export . --version=${{ steps.version.outputs.version }}
           conan upload --confirm --check --remote="${REMOTE_NAME}" xrpl/${{ steps.version.outputs.version }}
@@ -71,6 +73,8 @@ jobs:
       # 'develop' branch, see on-trigger.yml.
       - name: Upload Conan recipe (develop)
         if: ${{ github.event_name == 'push' }}
+        env:
+          REMOTE_NAME: ${{ inputs.remote_name }}
         run: |
           conan export . --version=develop
           conan upload --confirm --check --remote="${REMOTE_NAME}" xrpl/develop
@@ -79,6 +83,8 @@ jobs:
       # one of the 'release' branches, see on-pr.yml.
       - name: Upload Conan recipe (rc)
         if: ${{ github.event_name == 'pull_request' }}
+        env:
+          REMOTE_NAME: ${{ inputs.remote_name }}
         run: |
           conan export . --version=rc
           conan upload --confirm --check --remote="${REMOTE_NAME}" xrpl/rc
@@ -87,6 +93,8 @@ jobs:
       # release, see on-tag.yml.
       - name: Upload Conan recipe (release)
         if: ${{ startsWith(github.ref, 'refs/tags/') }}
+        env:
+          REMOTE_NAME: ${{ inputs.remote_name }}
         run: |
           conan export . --version=release
           conan upload --confirm --check --remote="${REMOTE_NAME}" xrpl/release
diff --git a/.github/workflows/upload-conan-deps.yml b/.github/workflows/upload-conan-deps.yml
index 92b72cf6a9..5d3712cf9e 100644
--- a/.github/workflows/upload-conan-deps.yml
+++ b/.github/workflows/upload-conan-deps.yml
@@ -34,7 +34,7 @@ on:
 
 env:
   CONAN_REMOTE_NAME: xrplf
-  CONAN_REMOTE_URL: https://conan.xrplf.org/repository/conan/
+  CONAN_REMOTE_URL: https://conan.ripplex.io
   NPROC_SUBTRACT: 2
 
 concurrency:
@@ -108,12 +108,10 @@ jobs:
 
       - name: Log into Conan remote
         if: ${{ github.repository == 'XRPLF/rippled' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') }}
-        run: conan remote login "${CONAN_REMOTE_NAME}" "${{ secrets.NEXUS_REMOTE_USERNAME }}" --password "${{ secrets.NEXUS_REMOTE_PASSWORD }}"
+        run: conan remote login "${CONAN_REMOTE_NAME}" "${{ secrets.CONAN_REMOTE_USERNAME }}" --password "${{ secrets.CONAN_REMOTE_PASSWORD }}"
 
       - name: Upload Conan packages
         if: ${{ github.repository == 'XRPLF/rippled' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') }}
         env:
           FORCE_OPTION: ${{ github.event.inputs.force_upload == 'true' && '--force' || '' }}
-          CONAN_LOGIN_USERNAME_XRPLF: ${{ secrets.NEXUS_REMOTE_USERNAME }}
-          CONAN_PASSWORD_XRPLF: ${{ secrets.NEXUS_REMOTE_PASSWORD }}
         run: conan upload "*" --remote="${CONAN_REMOTE_NAME}" --confirm ${FORCE_OPTION}
diff --git a/BUILD.md b/BUILD.md
index 847cd7bc1a..2ac24f2c5d 100644
--- a/BUILD.md
+++ b/BUILD.md
@@ -101,7 +101,7 @@ More information on customizing Conan can be found in the [Advanced Conan config
 Run the following command to add the `xrplf` remote, which hosts some of our dependencies:
 
 ```bash
-conan remote add --index 0 --force xrplf https://conan.xrplf.org/repository/conan/
+conan remote add --index 0 --force xrplf https://conan.ripplex.io
 ```
 
 ### Set Up Ccache
diff --git a/conan.lock b/conan.lock
index ae45a900b6..d80a6d0c57 100644
--- a/conan.lock
+++ b/conan.lock
@@ -1,43 +1,43 @@
 {
     "version": "0.5",
     "requires": [
-        "zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1777558780.503",
-        "xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1743678659.187",
-        "sqlite3/3.53.0#324ada52333108388a9a6108bfa96734%1776096494.149",
-        "soci/4.0.3#e726491a03468795453f7c83fc924a96%1751554127.172",
-        "snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1782307151.633168",
-        "secp256k1/0.7.1#b1f450b7f78a36fff75bb6934a356f3a%1782338841.3729",
-        "rocksdb/10.5.1#4a197eca381a3e5ae8adf8cffa5aacd0%1759820024.194",
-        "re2/20251105#8579cfd0bda4daf0683f9e3898f964b4%1772560729.95",
-        "protobuf/6.33.5#ff253ead763bd8d9904a52979cd21e81%1778763145.334",
-        "openssl/3.6.3#1163d4ddc603907084d08a6a0c6e580f%1782307150.583886",
-        "nudb/2.0.9#11149c73f8f2baff9a0198fe25971fc7%1774883011.384",
-        "lz4/1.10.0#982d9b673900f665a1da109e09c17cab%1775037240.923",
-        "libiconv/1.17#9923bc6dc6f106646d6967e0039a5ada%1774021608.288",
-        "libbacktrace/cci.20210118#a7691bfccd8caaf66309df196790a5a1%1722218217.276",
-        "libarchive/3.8.7#c446109bd1f1d8ba7936c94189bc50e6%1776147552.838",
+        "zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1778091116.056",
+        "xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1765850149.987",
+        "sqlite3/3.53.0#324ada52333108388a9a6108bfa96734%1778091117.311",
+        "soci/4.0.3#fe32b9ad5eb47e79ab9e45a68f363945%1774450067.231",
+        "snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1765850147.878",
+        "secp256k1/0.7.1#481881709eb0bdd0185a12b912bbe8ad%1770910500.329",
+        "rocksdb/10.5.1#4a197eca381a3e5ae8adf8cffa5aacd0%1765850186.86",
+        "re2/20251105#8579cfd0bda4daf0683f9e3898f964b4%1774398111.888",
+        "protobuf/6.33.5#d96d52ba5baaaa532f47bda866ad87a5%1774467363.12",
+        "openssl/3.6.2#4789bbf131b77d0515d15e094c8f697f%1778071755.506",
+        "nudb/2.0.9#11149c73f8f2baff9a0198fe25971fc7%1775040983.408",
+        "lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1765850143.914",
+        "libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1765842973.492",
+        "libbacktrace/cci.20210118#a7691bfccd8caaf66309df196790a5a1%1765842973.03",
+        "libarchive/3.8.7#c446109bd1f1d8ba7936c94189bc50e6%1778091117.848",
         "jemalloc/5.3.1#1fc58d55316041f10fbc1e8a2eae632a%1776700028.228",
-        "gtest/1.17.0#5224b3b3ff3b4ce1133cbdd27d53ee7d%1755784855.585",
-        "grpc/1.81.1#5217e6ef0544c42b46f4af35d5e7f649%1782307148.845616",
-        "ed25519/2015.03#ae761bdc52730a843f0809bdf6c1b1f6%1782307148.15562",
-        "date/3.0.4#862e11e80030356b53c2c38599ceb32b%1754573467.979",
-        "c-ares/1.34.6#545240bb1c40e2cacd4362d6b8967650%1766500685.317",
-        "bzip2/1.0.8#c470882369c2d95c5c77e970c0c7e321%1762886692.465",
-        "boost/1.91.0#ea540ca2133d831b560036aa24dece3c%1778050991.9",
-        "abseil/20250127.0#bb0baf1f362bc4a725a24eddd419b8f7%1782307147.395833"
+        "gtest/1.17.0#5224b3b3ff3b4ce1133cbdd27d53ee7d%1768312129.152",
+        "grpc/1.81.0#2fb144aeb47e7f35c6ebb0e5f35bed31%1781620605.685",
+        "ed25519/2015.03#ae761bdc52730a843f0809bdf6c1b1f6%1765850143.772",
+        "date/3.0.4#862e11e80030356b53c2c38599ceb32b%1765850143.772",
+        "c-ares/1.34.6#545240bb1c40e2cacd4362d6b8967650%1774439234.681",
+        "bzip2/1.0.8#c470882369c2d95c5c77e970c0c7e321%1765850143.837",
+        "boost/1.91.0#ea540ca2133d831b560036aa24dece3c%1778091165.282",
+        "abseil/20250127.0#bb0baf1f362bc4a725a24eddd419b8f7%1774365460.196"
     ],
     "build_requires": [
-        "zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1777558780.503",
-        "strawberryperl/5.32.1.1#8d114504d172cfea8ea1662d09b6333e%1751971032.423",
-        "protobuf/6.33.5#ff253ead763bd8d9904a52979cd21e81%1778763145.334",
-        "nasm/2.16.01#31e26f2ee3c4346ecd347911bd126904%1745483323.489",
+        "zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1778091116.056",
+        "strawberryperl/5.32.1.1#8d114504d172cfea8ea1662d09b6333e%1774447376.964",
+        "protobuf/6.33.5#d96d52ba5baaaa532f47bda866ad87a5%1774467363.12",
+        "nasm/2.16.01#31e26f2ee3c4346ecd347911bd126904%1765850144.707",
         "msys2/cci.latest#d22fe7b2808f5fd34d0a7923ace9c54f%1770657326.649",
-        "m4/1.4.19#34c4bbc3eeebe98ca6edf2f52d602e7d%1777282960.259",
-        "cmake/4.3.3#840cf00ea09777e05c2050a50a82c722%1781521538.233",
-        "b2/5.4.2#ffd6084a119587e70f11cd45d1a386e2%1766594659.866",
+        "m4/1.4.19#4523e4347b55cd26ae918bd5770cab9a%1778062762.471",
+        "cmake/4.3.0#b939a42e98f593fb34d3a8c5cc860359%1774439249.183",
+        "b2/5.4.2#ffd6084a119587e70f11cd45d1a386e2%1774439233.447",
         "automake/1.16.5#b91b7c384c3deaa9d535be02da14d04f%1755524470.56",
         "autoconf/2.71#51077f068e61700d65bb05541ea1e4b0%1731054366.86",
-        "abseil/20250127.0#bb0baf1f362bc4a725a24eddd419b8f7%1782307147.395833"
+        "abseil/20250127.0#bb0baf1f362bc4a725a24eddd419b8f7%1774365460.196"
     ],
     "python_requires": [],
     "overrides": {
@@ -57,7 +57,7 @@
             "boost/1.91.0"
         ],
         "lz4/[>=1.9.4 <2]": [
-            "lz4/1.10.0#982d9b673900f665a1da109e09c17cab"
+            "lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504"
         ]
     },
     "config_requires": []
diff --git a/conan/lockfile/regenerate.sh b/conan/lockfile/regenerate.sh
index 98ee6f7c99..1aa47628f0 100755
--- a/conan/lockfile/regenerate.sh
+++ b/conan/lockfile/regenerate.sh
@@ -14,7 +14,7 @@ export CONAN_HOME="$TEMP_DIR"
 # Ensure that the xrplf remote is the first to be consulted, so any recipes we
 # patched are used. We also add it there to not created huge diff when the
 # official Conan Center Index is updated.
-conan remote add --force --index 0 xrplf https://conan.xrplf.org/repository/conan/
+conan remote add --force --index 0 xrplf https://conan.ripplex.io
 
 # Delete any existing lockfile.
 rm -f conan.lock
diff --git a/conanfile.py b/conanfile.py
index 2733d4fc9c..5b78dc22e3 100644
--- a/conanfile.py
+++ b/conanfile.py
@@ -28,10 +28,10 @@ class Xrpl(ConanFile):
 
     requires = [
         "ed25519/2015.03",
-        "grpc/1.81.1",
+        "grpc/1.81.0",
         "libarchive/3.8.7",
         "nudb/2.0.9",
-        "openssl/3.6.3",
+        "openssl/3.6.2",
         "secp256k1/0.7.1",
         "soci/4.0.3",
         "zlib/1.3.2",
diff --git a/docs/build/advanced_conan.md b/docs/build/advanced_conan.md
index 26b88ef186..aae17e385a 100644
--- a/docs/build/advanced_conan.md
+++ b/docs/build/advanced_conan.md
@@ -34,7 +34,7 @@ higher index than the default Conan Center remote, so it is consulted first. You
 can do this by running:
 
 ```bash
-conan remote add --index 0 --force xrplf https://conan.xrplf.org/repository/conan/
+conan remote add --index 0 --force xrplf https://conan.ripplex.io
 ```
 
 Alternatively, you can pull our recipes from the repository and export them locally: