From 29b17124a78f5fbda23c265f78dcb0df108cf630 Mon Sep 17 00:00:00 2001 From: Chenna Keshava Date: Tue, 30 May 2023 13:59:27 -0700 Subject: [PATCH 1/3] Strongly typed wrapper class for Amendments Singleton ledger object --- src/ripple/app/tx/impl/Change.cpp | 4 ++ src/ripple/ledger/ApplyView.h | 16 +++--- src/ripple/ledger/impl/ReadView.cpp | 12 +++-- src/ripple/ledger/impl/View.cpp | 14 ++--- src/ripple/protocol/AcctRoot.h | 69 ++++++++++++++++-------- src/ripple/protocol/Amendments.h | 62 +++++++++++++++++++++ src/ripple/protocol/Indexes.h | 2 +- src/ripple/protocol/Keylet.h | 16 ++++++ src/ripple/protocol/LedgerEntryWrapper.h | 30 ++++++----- src/ripple/protocol/impl/Indexes.cpp | 5 +- 10 files changed, 173 insertions(+), 57 deletions(-) create mode 100644 src/ripple/protocol/Amendments.h diff --git a/src/ripple/app/tx/impl/Change.cpp b/src/ripple/app/tx/impl/Change.cpp index 7387a231e60..740a8ca16a6 100644 --- a/src/ripple/app/tx/impl/Change.cpp +++ b/src/ripple/app/tx/impl/Change.cpp @@ -253,6 +253,10 @@ Change::applyAmendment() auto const k = keylet::amendments(); + // amendmentObject is better off being a SLE rather than a + // AmendmentsImpl It is accessing multiple get/set methods from + // STObject. It is expensive to accomplish the same with + // AmendmentsObject. SLE::pointer amendmentObject = view().peekSLE(k); if (!amendmentObject) diff --git a/src/ripple/ledger/ApplyView.h b/src/ripple/ledger/ApplyView.h index f7578411a23..c55aecf8b96 100644 --- a/src/ripple/ledger/ApplyView.h +++ b/src/ripple/ledger/ApplyView.h @@ -201,9 +201,11 @@ class ApplyView : public ReadView erase(std::shared_ptr const& sle) = 0; template - requires(std::is_convertible_v< - decltype(std::declval().slePtr()), - std::shared_ptr const&>) void erase(T& wrapper) + requires(std::is_convertible_v< + decltype(std::declval().slePtr()), + std::shared_ptr const&>) + void + erase(T& wrapper) { erase(wrapper.slePtr()); } @@ -249,9 +251,11 @@ class ApplyView : public ReadView update(std::shared_ptr const& sle) = 0; template - requires(std::is_convertible_v< - decltype(std::declval().slePtr()), - std::shared_ptr const&>) void update(T& wrapper) + requires(std::is_convertible_v< + decltype(std::declval().slePtr()), + std::shared_ptr const&>) + void + update(T& wrapper) { update(wrapper.slePtr()); } diff --git a/src/ripple/ledger/impl/ReadView.cpp b/src/ripple/ledger/impl/ReadView.cpp index 27d5ff095f2..53effb2be01 100644 --- a/src/ripple/ledger/impl/ReadView.cpp +++ b/src/ripple/ledger/impl/ReadView.cpp @@ -18,6 +18,7 @@ //============================================================================== #include +#include namespace ripple { @@ -76,13 +77,16 @@ makeRulesGivenLedger( DigestAwareReadView const& ledger, std::unordered_set> const& presets) { - Keylet const k = keylet::amendments(); + AmendmentsKeylet const k = keylet::amendments(); std::optional digest = ledger.digest(k.key); if (digest) { - auto const sle = ledger.readSLE(k); - if (sle) - return Rules(presets, digest, sle->getFieldV256(sfAmendments)); + auto const amendsObj = ledger.read(k); + if (amendsObj) + return Rules( + presets, + digest, + amendsObj->slePtr()->getFieldV256(sfAmendments)); } return Rules(presets); } diff --git a/src/ripple/ledger/impl/View.cpp b/src/ripple/ledger/impl/View.cpp index a7f3828eb40..c567b283b0d 100644 --- a/src/ripple/ledger/impl/View.cpp +++ b/src/ripple/ledger/impl/View.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -607,11 +608,11 @@ getEnabledAmendments(ReadView const& view) { std::set amendments; - if (auto const sle = view.readSLE(keylet::amendments())) + if (auto const amendsObj = view.read(keylet::amendments())) { - if (sle->isFieldPresent(sfAmendments)) + if (amendsObj->slePtr()->isFieldPresent(sfAmendments)) { - auto const& v = sle->getFieldV256(sfAmendments); + auto const& v = amendsObj->slePtr()->getFieldV256(sfAmendments); amendments.insert(v.begin(), v.end()); } } @@ -624,14 +625,15 @@ getMajorityAmendments(ReadView const& view) { majorityAmendments_t ret; - if (auto const sle = view.readSLE(keylet::amendments())) + if (auto const amendsObj = view.read(keylet::amendments())) { - if (sle->isFieldPresent(sfMajorities)) + if (amendsObj->slePtr()->isFieldPresent(sfMajorities)) { using tp = NetClock::time_point; using d = tp::duration; - auto const majorities = sle->getFieldArray(sfMajorities); + auto const majorities = + amendsObj->slePtr()->getFieldArray(sfMajorities); for (auto const& m : majorities) ret[m.getFieldH256(sfAmendment)] = diff --git a/src/ripple/protocol/AcctRoot.h b/src/ripple/protocol/AcctRoot.h index c9e27fd4b3e..a4688d9c5ab 100644 --- a/src/ripple/protocol/AcctRoot.h +++ b/src/ripple/protocol/AcctRoot.h @@ -69,7 +69,8 @@ class AcctRootImpl final : public LedgerEntryWrapper } void - setSequence(std::uint32_t seq) requires Writable + setSequence(std::uint32_t seq) + requires Writable { wrapped_->at(sfSequence) = seq; } @@ -81,7 +82,8 @@ class AcctRootImpl final : public LedgerEntryWrapper } void - setBalance(STAmount const& amount) requires Writable + setBalance(STAmount const& amount) + requires Writable { wrapped_->at(sfBalance) = amount; } @@ -93,7 +95,8 @@ class AcctRootImpl final : public LedgerEntryWrapper } void - setOwnerCount(std::uint32_t newCount) requires Writable + setOwnerCount(std::uint32_t newCount) + requires Writable { wrapped_->at(sfOwnerCount) = newCount; } @@ -105,7 +108,8 @@ class AcctRootImpl final : public LedgerEntryWrapper } void - setPreviousTxnID(uint256 prevTxID) requires Writable + setPreviousTxnID(uint256 prevTxID) + requires Writable { wrapped_->at(sfPreviousTxnID) = prevTxID; } @@ -117,7 +121,8 @@ class AcctRootImpl final : public LedgerEntryWrapper } void - setPreviousTxnLgrSeq(std::uint32_t prevTxLgrSeq) requires Writable + setPreviousTxnLgrSeq(std::uint32_t prevTxLgrSeq) + requires Writable { wrapped_->at(sfPreviousTxnLgrSeq) = prevTxLgrSeq; } @@ -129,13 +134,15 @@ class AcctRootImpl final : public LedgerEntryWrapper } void - setAccountTxnID(uint256 const& newAcctTxnID) requires Writable + setAccountTxnID(uint256 const& newAcctTxnID) + requires Writable { this->setOptional(sfAccountTxnID, newAcctTxnID); } void - clearAccountTxnID() requires Writable + clearAccountTxnID() + requires Writable { this->clearOptional(sfAccountTxnID); } @@ -147,13 +154,15 @@ class AcctRootImpl final : public LedgerEntryWrapper } void - setRegularKey(AccountID const& newRegKey) requires Writable + setRegularKey(AccountID const& newRegKey) + requires Writable { this->setOptional(sfRegularKey, newRegKey); } void - clearRegularKey() requires Writable + clearRegularKey() + requires Writable { this->clearOptional(sfRegularKey); } @@ -165,7 +174,8 @@ class AcctRootImpl final : public LedgerEntryWrapper } void - setEmailHash(uint128 const& newEmailHash) requires Writable + setEmailHash(uint128 const& newEmailHash) + requires Writable { this->setOrClearBaseUintIfZero(sfEmailHash, newEmailHash); } @@ -177,7 +187,8 @@ class AcctRootImpl final : public LedgerEntryWrapper } void - setWalletLocator(uint256 const& newWalletLocator) requires Writable + setWalletLocator(uint256 const& newWalletLocator) + requires Writable { this->setOrClearBaseUintIfZero(sfWalletLocator, newWalletLocator); } @@ -195,7 +206,8 @@ class AcctRootImpl final : public LedgerEntryWrapper } void - setMessageKey(Blob const& newMessageKey) requires Writable + setMessageKey(Blob const& newMessageKey) + requires Writable { this->setOrClearVLIfEmpty(sfMessageKey, newMessageKey); } @@ -207,13 +219,15 @@ class AcctRootImpl final : public LedgerEntryWrapper } void - setTransferRate(std::uint32_t newTransferRate) requires Writable + setTransferRate(std::uint32_t newTransferRate) + requires Writable { this->setOptional(sfTransferRate, newTransferRate); } void - clearTransferRate() requires Writable + clearTransferRate() + requires Writable { this->clearOptional(sfTransferRate); } @@ -225,7 +239,8 @@ class AcctRootImpl final : public LedgerEntryWrapper } void - setDomain(Blob const& newDomain) requires Writable + setDomain(Blob const& newDomain) + requires Writable { this->setOrClearVLIfEmpty(sfDomain, newDomain); } @@ -237,13 +252,15 @@ class AcctRootImpl final : public LedgerEntryWrapper } void - setTickSize(std::uint8_t newTickSize) requires Writable + setTickSize(std::uint8_t newTickSize) + requires Writable { this->setOptional(sfTickSize, newTickSize); } void - clearTickSize() requires Writable + clearTickSize() + requires Writable { this->clearOptional(sfTickSize); } @@ -255,13 +272,15 @@ class AcctRootImpl final : public LedgerEntryWrapper } void - setTicketCount(std::uint32_t newTicketCount) requires Writable + setTicketCount(std::uint32_t newTicketCount) + requires Writable { this->setOptional(sfTicketCount, newTicketCount); } void - clearTicketCount() requires Writable + clearTicketCount() + requires Writable { this->clearOptional(sfTicketCount); } @@ -273,13 +292,15 @@ class AcctRootImpl final : public LedgerEntryWrapper } void - setNFTokenMinter(AccountID const& newMinter) requires Writable + setNFTokenMinter(AccountID const& newMinter) + requires Writable { this->setOptional(sfNFTokenMinter, newMinter); } void - clearNFTokenMinter() requires Writable + clearNFTokenMinter() + requires Writable { this->clearOptional(sfNFTokenMinter); } @@ -291,7 +312,8 @@ class AcctRootImpl final : public LedgerEntryWrapper } void - setMintedNFTokens(std::uint32_t newMintedCount) requires Writable + setMintedNFTokens(std::uint32_t newMintedCount) + requires Writable { this->setOptional(sfMintedNFTokens, newMintedCount); } @@ -303,7 +325,8 @@ class AcctRootImpl final : public LedgerEntryWrapper } void - setBurnedNFTokens(std::uint32_t newBurnedCount) requires Writable + setBurnedNFTokens(std::uint32_t newBurnedCount) + requires Writable { this->setOptional(sfBurnedNFTokens, newBurnedCount); } diff --git a/src/ripple/protocol/Amendments.h b/src/ripple/protocol/Amendments.h new file mode 100644 index 00000000000..58ebc70caa0 --- /dev/null +++ b/src/ripple/protocol/Amendments.h @@ -0,0 +1,62 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2021 Ripple Labs Inc. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef RIPPLE_PROTOCOL_AMENDMENTS_H_INCLUDED +#define RIPPLE_PROTOCOL_AMENDMENTS_H_INCLUDED + +#include +// #include +// #include + +namespace ripple { + +template +class AmendmentsImpl final : public LedgerEntryWrapper +{ +private: + using Base = LedgerEntryWrapper; + using SleT = typename Base::SleT; + using Base::wrapped_; + + // This constructor is private so only the factory functions can + // construct an AmendmentsImpl. + AmendmentsImpl(std::shared_ptr&& w) : Base(std::move(w)) + { + } + + // Friend declarations of factory functions. + // + // For classes that contain factories we must declare the entire class + // as a friend unless the class declaration is visible at this point. + friend class ReadView; + friend class ApplyView; + +public: + // Conversion operator from AmendmentsImpl to AmendmentsImpl. + operator AmendmentsImpl() const + { + return AmendmentsImpl( + std::const_pointer_cast>( + wrapped_)); + } +}; + +} // namespace ripple + +#endif // RIPPLE_PROTOCOL_AMENDMENTS_H_INCLUDED diff --git a/src/ripple/protocol/Indexes.h b/src/ripple/protocol/Indexes.h index e7170eff7cc..96ab8e88633 100644 --- a/src/ripple/protocol/Indexes.h +++ b/src/ripple/protocol/Indexes.h @@ -54,7 +54,7 @@ AccountRootKeylet account(AccountID const& id) noexcept; /** The index of the amendment table */ -Keylet const& +AmendmentsKeylet const& amendments() noexcept; /** Any item that can be in an owner dir. */ diff --git a/src/ripple/protocol/Keylet.h b/src/ripple/protocol/Keylet.h index c34b484a150..71c9905586b 100644 --- a/src/ripple/protocol/Keylet.h +++ b/src/ripple/protocol/Keylet.h @@ -95,6 +95,22 @@ static_assert(std::is_move_assignable_v); static_assert(std::is_nothrow_destructible_v); #endif +template +class AmendmentsImpl; + +struct AmendmentsKeylet final : public KeyletBase +{ + template + using TWrapped = AmendmentsImpl; + + using KeyletBase::check; + + explicit AmendmentsKeylet(uint256 const& key) + : KeyletBase(ltAMENDMENTS, key) + { + } +}; + template class AcctRootImpl; diff --git a/src/ripple/protocol/LedgerEntryWrapper.h b/src/ripple/protocol/LedgerEntryWrapper.h index fa082a62d4a..0f60740cc67 100644 --- a/src/ripple/protocol/LedgerEntryWrapper.h +++ b/src/ripple/protocol/LedgerEntryWrapper.h @@ -66,9 +66,8 @@ class LedgerEntryWrapper // Helper functions that are useful to some derived classes. template void - setOptional( - SF const& field, - T const& value) requires Writable&& std::is_base_of_v + setOptional(SF const& field, T const& value) + requires Writable && std::is_base_of_v { if (!wrapped_->isFieldPresent(field)) wrapped_->makeFieldPresent(field); @@ -78,8 +77,8 @@ class LedgerEntryWrapper template void - clearOptional( - SF const& field) requires Writable&& std::is_base_of_v + clearOptional(SF const& field) + requires Writable && std::is_base_of_v { if (wrapped_->isFieldPresent(field)) wrapped_->makeFieldAbsent(field); @@ -96,10 +95,8 @@ class LedgerEntryWrapper template void - setOrClearBaseUintIfZero( - SF const& field, - base_uint const& - value) requires Writable&& std::is_base_of_v + setOrClearBaseUintIfZero(SF const& field, base_uint const& value) + requires Writable && std::is_base_of_v { if (value.signum() == 0) return clearOptional(field); @@ -111,7 +108,8 @@ class LedgerEntryWrapper } void - setOrClearVLIfEmpty(SF_VL const& field, Blob const& value) requires Writable + setOrClearVLIfEmpty(SF_VL const& field, Blob const& value) + requires Writable { if (value.empty()) return clearOptional(field); @@ -137,7 +135,8 @@ class LedgerEntryWrapper } [[nodiscard]] std::shared_ptr const& - slePtr() requires Writable + slePtr() + requires Writable { return wrapped_; } @@ -155,19 +154,22 @@ class LedgerEntryWrapper } void - replaceAllFlags(std::uint32_t newFlags) requires Writable + replaceAllFlags(std::uint32_t newFlags) + requires Writable { wrapped_->at(sfFlags) = newFlags; } void - setFlag(std::uint32_t flagsToSet) requires Writable + setFlag(std::uint32_t flagsToSet) + requires Writable { replaceAllFlags(flags() | flagsToSet); } void - clearFlag(std::uint32_t flagsToClear) requires Writable + clearFlag(std::uint32_t flagsToClear) + requires Writable { replaceAllFlags(flags() & ~flagsToClear); } diff --git a/src/ripple/protocol/impl/Indexes.cpp b/src/ripple/protocol/impl/Indexes.cpp index 2cc80ff41e6..70528c60f0c 100644 --- a/src/ripple/protocol/impl/Indexes.cpp +++ b/src/ripple/protocol/impl/Indexes.cpp @@ -159,11 +159,10 @@ skip(LedgerIndex ledger) noexcept std::uint32_t(static_cast(ledger) >> 16))}; } -Keylet const& +AmendmentsKeylet const& amendments() noexcept { - static Keylet const ret{ - ltAMENDMENTS, indexHash(LedgerNameSpace::AMENDMENTS)}; + static AmendmentsKeylet const ret(indexHash(LedgerNameSpace::AMENDMENTS)); return ret; } From 29a9259b47454c3b43788ae6ae2d4aeb79ad8270 Mon Sep 17 00:00:00 2001 From: Chenna Keshava Date: Thu, 1 Jun 2023 10:49:19 -0700 Subject: [PATCH 2/3] Type-alias for read-only and writable AmendmentsImpl template instances --- src/ripple/app/tx/impl/Change.cpp | 4 ++-- src/ripple/protocol/Amendments.h | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/ripple/app/tx/impl/Change.cpp b/src/ripple/app/tx/impl/Change.cpp index 740a8ca16a6..a0985e2eb81 100644 --- a/src/ripple/app/tx/impl/Change.cpp +++ b/src/ripple/app/tx/impl/Change.cpp @@ -254,9 +254,9 @@ Change::applyAmendment() auto const k = keylet::amendments(); // amendmentObject is better off being a SLE rather than a - // AmendmentsImpl It is accessing multiple get/set methods from + // Amendments object. It is accessing multiple get/set methods from // STObject. It is expensive to accomplish the same with - // AmendmentsObject. + // Amendments object. SLE::pointer amendmentObject = view().peekSLE(k); if (!amendmentObject) diff --git a/src/ripple/protocol/Amendments.h b/src/ripple/protocol/Amendments.h index 58ebc70caa0..86bd5db14eb 100644 --- a/src/ripple/protocol/Amendments.h +++ b/src/ripple/protocol/Amendments.h @@ -21,8 +21,6 @@ #define RIPPLE_PROTOCOL_AMENDMENTS_H_INCLUDED #include -// #include -// #include namespace ripple { @@ -57,6 +55,9 @@ class AmendmentsImpl final : public LedgerEntryWrapper } }; +using Amendments = AmendmentsImpl; +using AmendmentsRd = AmendmentsImpl; + } // namespace ripple #endif // RIPPLE_PROTOCOL_AMENDMENTS_H_INCLUDED From b20ddb8c092fca059aa6d5e7b20004dc747ae480 Mon Sep 17 00:00:00 2001 From: Chenna Keshava Date: Wed, 7 Jun 2023 12:49:31 -0700 Subject: [PATCH 3/3] Update copyrights information to the year 2023 --- src/ripple/protocol/Amendments.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ripple/protocol/Amendments.h b/src/ripple/protocol/Amendments.h index 86bd5db14eb..f6cc09829fc 100644 --- a/src/ripple/protocol/Amendments.h +++ b/src/ripple/protocol/Amendments.h @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ /* This file is part of rippled: https://github.com/ripple/rippled - Copyright (c) 2021 Ripple Labs Inc. + Copyright (c) 2023 Ripple Labs Inc. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above