1#include <xrpl/tx/invariants/FreezeInvariant.h>
3#include <xrpl/basics/Log.h>
4#include <xrpl/beast/utility/Journal.h>
5#include <xrpl/beast/utility/instrumentation.h>
6#include <xrpl/ledger/ReadView.h>
7#include <xrpl/protocol/AccountID.h>
8#include <xrpl/protocol/Feature.h>
9#include <xrpl/protocol/Indexes.h>
10#include <xrpl/protocol/Issue.h>
11#include <xrpl/protocol/LedgerFormats.h>
12#include <xrpl/protocol/SField.h>
13#include <xrpl/protocol/STLedgerEntry.h>
14#include <xrpl/protocol/STTx.h>
15#include <xrpl/protocol/TER.h>
16#include <xrpl/protocol/XRPAmount.h>
17#include <xrpl/tx/invariants/InvariantCheckPrivilege.h>
43 if (balanceChange.signum() == 0)
75 [[maybe_unused]]
bool const enforce = view.
rules().
enabled(featureDeepFreeze);
76 bool const fixOverrideFreeze = view.
rules().
enabled(fixCleanup3_4_0);
79 auto const& [issue, changes] = entry;
80 auto const issuerSle =
findIssuer(issue.account, view);
89 "xrpl::TransfersNotFrozen::finalize : enforce "
102 XRPL_ASSERT(
after,
"xrpl::TransfersNotFrozen::isValidEntry : valid after.");
108 if (
after->getType() == ltACCOUNT_ROOT)
120 return after->getType() == ltRIPPLE_STATE && (!before || before->getType() == ltRIPPLE_STATE);
129 auto const getBalance = [](
auto const& line,
auto const& other,
bool zero) {
130 STAmount const amt = line ? line->at(sfBalance) : other->at(sfBalance).
zeroed();
131 return zero ? amt.
zeroed() : amt;
139 auto const balanceBefore = getBalance(before,
after,
false);
146 auto const balanceAfter = getBalance(
after, before, isDelete);
148 return balanceAfter - balanceBefore;
156 "xrpl::TransfersNotFrozen::recordBalance : valid trustline "
161 changes.senders.emplace_back(std::move(change));
165 changes.receivers.emplace_back(std::move(change));
172 auto const balanceChangeSign = balanceChange.
signum();
173 auto const currency =
after->at(sfBalance).get<
Issue>().currency;
177 {currency,
after->at(sfHighLimit).getIssuer()},
178 {.line =
after, .balanceChangeSign = balanceChangeSign});
182 {currency,
after->at(sfLowLimit).getIssuer()},
183 {.line =
after, .balanceChangeSign = -balanceChangeSign});
204 bool fixOverrideFreeze)
211 bool const globalFreeze = issuer->isFlag(lsfGlobalFreeze);
226 for (
auto const& change : actors)
228 bool const high = change.line->at(sfLowLimit).getIssuer() == issuer->at(sfAccount);
247 bool fixOverrideFreeze)
251 bool const deepFreeze = change.
line->isFlag(high ? lsfLowDeepFreeze : lsfHighDeepFreeze);
252 bool const frozen = globalFreeze || deepFreeze || freeze;
262 bool const isAMMLine = change.
line->isFlag(lsfAMMNode);
265 JLOG(j.
debug()) <<
"Invariant check allowing funds to be moved "
267 <<
" a frozen trustline for a freeze privileged transaction "
272 JLOG(j.
fatal()) <<
"Invariant failed: Attempting to move frozen funds for "
277 "xrpl::TransfersNotFrozen::validateFrozenState : enforce "
A generic endpoint for log messages.
A currency issued by an account.
virtual Rules const & rules() const =0
Returns the tx processing rules.
virtual SLE::const_pointer read(Keylet const &k) const =0
Return the state item associated with a key.
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
int signum() const noexcept
STAmount zeroed() const
Returns a zero value with the same issuer and currency.
std::shared_ptr< STLedgerEntry const > const & const_ref
std::shared_ptr< STLedgerEntry const > const_pointer
uint256 getTransactionID() const
void recordBalance(Issue const &issue, BalanceChange change)
std::map< AccountID, SLE::const_pointer const > possibleIssuers_
static bool validateFrozenState(BalanceChange const &change, bool high, STTx const &tx, beast::Journal const &j, bool enforce, bool globalFreeze, bool fixOverrideFreeze)
static STAmount calculateBalanceChange(SLE::const_ref before, SLE::const_ref after, bool isDelete)
void recordBalanceChanges(SLE::const_ref after, STAmount const &balanceChange)
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
bool isValidEntry(SLE::const_ref before, SLE::const_ref after)
static bool validateIssuerChanges(SLE::const_ref issuer, IssuerChanges const &changes, STTx const &tx, beast::Journal const &j, bool enforce, bool fixOverrideFreeze)
void visitEntry(bool, SLE::const_ref, SLE::const_ref)
SLE::const_pointer findIssuer(AccountID const &issuerID, ReadView const &view)
Keylet account(AccountID const &id) noexcept
AccountID root.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
bool hasPrivilege(STTx const &tx, Privilege priv)
bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
TERSubset< CanCvtToTER > TER
SLE::const_pointer const line
int const balanceChangeSign
std::vector< BalanceChange > senders
std::vector< BalanceChange > receivers