Skip to content

Commit

Permalink
Add global access to the current ledger rules:
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
seelabs committed Apr 25, 2024
1 parent b84f7e7 commit 95cd1fe
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/ripple/app/tx/impl/Transactor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -831,8 +831,11 @@ Transactor::operator()()
{
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)};
NumberSO stNumberSO{view().rules().enabled(fixUniversalNumber)};
CurrentTransactionRulesGuard currentTransctionRulesGuard(view().rules());

#ifdef DEBUG
{
Expand Down
37 changes: 37 additions & 0 deletions src/ripple/protocol/Rules.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <ripple/basics/base_uint.h>
#include <ripple/beast/hash/uhash.h>
#include <ripple/protocol/STVector256.h>

#include <unordered_set>

namespace ripple {
Expand All @@ -42,9 +43,14 @@ class Rules
public:
Rules(Rules const&) = default;

Rules(Rules&&) = default;

Rules&
operator=(Rules const&) = default;

Rules&
operator=(Rules&&) = default;

Rules() = delete;

/** Construct an empty rule set.
Expand Down Expand Up @@ -90,5 +96,36 @@ class Rules
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
#endif
25 changes: 25 additions & 0 deletions src/ripple/protocol/impl/Rules.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,36 @@
*/
//==============================================================================

#include <ripple/basics/LocalValue.h>
#include <ripple/protocol/Feature.h>
#include <ripple/protocol/Rules.h>

#include <optional>

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
{
private:
Expand Down

0 comments on commit 95cd1fe

Please sign in to comment.