Add global access to the current ledger rules:

It can be difficult to make transaction breaking changes to low level
code because the low level code does not have access to a ledger and the
current activated amendments in that ledger (the "rules"). This patch
adds global access to the current ledger rules as a `std::optional`. If
the optional is not seated, then there is no active transaction.
This commit is contained in:
seelabs
2024-04-18 17:12:05 -04:00
committed by Scott Determan
parent b422e71eed
commit b65cea1984
3 changed files with 65 additions and 0 deletions

View File

@@ -831,8 +831,11 @@ Transactor::operator()()
{ {
JLOG(j_.trace()) << "apply: " << ctx_.tx.getTransactionID(); JLOG(j_.trace()) << "apply: " << ctx_.tx.getTransactionID();
// raii classes for the current ledger rules. fixSTAmountCanonicalize and
// fixSTAmountCanonicalize predate the rulesGuard and should be replaced.
STAmountSO stAmountSO{view().rules().enabled(fixSTAmountCanonicalize)}; STAmountSO stAmountSO{view().rules().enabled(fixSTAmountCanonicalize)};
NumberSO stNumberSO{view().rules().enabled(fixUniversalNumber)}; NumberSO stNumberSO{view().rules().enabled(fixUniversalNumber)};
CurrentTransactionRulesGuard currentTransctionRulesGuard(view().rules());
#ifdef DEBUG #ifdef DEBUG
{ {

View File

@@ -23,6 +23,7 @@
#include <ripple/basics/base_uint.h> #include <ripple/basics/base_uint.h>
#include <ripple/beast/hash/uhash.h> #include <ripple/beast/hash/uhash.h>
#include <ripple/protocol/STVector256.h> #include <ripple/protocol/STVector256.h>
#include <unordered_set> #include <unordered_set>
namespace ripple { namespace ripple {
@@ -42,9 +43,14 @@ private:
public: public:
Rules(Rules const&) = default; Rules(Rules const&) = default;
Rules(Rules&&) = default;
Rules& Rules&
operator=(Rules const&) = default; operator=(Rules const&) = default;
Rules&
operator=(Rules&&) = default;
Rules() = delete; Rules() = delete;
/** Construct an empty rule set. /** Construct an empty rule set.
@@ -90,5 +96,36 @@ public:
operator!=(Rules const& other) const; operator!=(Rules const& other) const;
}; };
std::optional<Rules> const&
getCurrentTransactionRules();
void
setCurrentTransactionRules(std::optional<Rules> r);
/** RAII class to set and restore the current transaction rules
*/
class CurrentTransactionRulesGuard
{
public:
explicit CurrentTransactionRulesGuard(Rules r)
: saved_(getCurrentTransactionRules())
{
setCurrentTransactionRules(std::move(r));
}
~CurrentTransactionRulesGuard()
{
setCurrentTransactionRules(saved_);
}
CurrentTransactionRulesGuard() = delete;
CurrentTransactionRulesGuard(CurrentTransactionRulesGuard const&) = delete;
CurrentTransactionRulesGuard&
operator=(CurrentTransactionRulesGuard const&) = delete;
private:
std::optional<Rules> saved_;
};
} // namespace ripple } // namespace ripple
#endif #endif

View File

@@ -17,11 +17,36 @@
*/ */
//============================================================================== //==============================================================================
#include <ripple/basics/LocalValue.h>
#include <ripple/protocol/Feature.h> #include <ripple/protocol/Feature.h>
#include <ripple/protocol/Rules.h> #include <ripple/protocol/Rules.h>
#include <optional>
namespace ripple { namespace ripple {
namespace {
// Use a static inisde a function to help prevent order-of-initialization issues
LocalValue<std::optional<Rules>>&
getCurrentTransactionRulesRef()
{
static LocalValue<std::optional<Rules>> r;
return r;
}
} // namespace
std::optional<Rules> const&
getCurrentTransactionRules()
{
return *getCurrentTransactionRulesRef();
}
void
setCurrentTransactionRules(std::optional<Rules> r)
{
*getCurrentTransactionRulesRef() = std::move(r);
}
class Rules::Impl class Rules::Impl
{ {
private: private: