1#include <xrpl/tx/invariants/LoanBrokerInvariant.h>
3#include <xrpl/basics/Log.h>
4#include <xrpl/beast/utility/Journal.h>
5#include <xrpl/ledger/ReadView.h>
6#include <xrpl/ledger/helpers/TokenHelpers.h>
7#include <xrpl/protocol/Feature.h>
8#include <xrpl/protocol/Indexes.h>
9#include <xrpl/protocol/LedgerFormats.h>
10#include <xrpl/protocol/SField.h>
11#include <xrpl/protocol/STLedgerEntry.h>
12#include <xrpl/protocol/STNumber.h>
13#include <xrpl/protocol/STTx.h>
14#include <xrpl/protocol/TER.h>
15#include <xrpl/protocol/TxFormats.h>
16#include <xrpl/protocol/XRPAmount.h>
25 if (
after->getType() == ltLOAN_BROKER)
28 broker.brokerBefore = before;
29 broker.brokerAfter =
after;
31 else if (
after->getType() == ltACCOUNT_ROOT &&
after->isFieldPresent(sfLoanBrokerID))
33 auto const& loanBrokerID =
after->at(sfLoanBrokerID);
37 else if (
after->getType() == ltRIPPLE_STATE)
41 else if (
after->getType() == ltMPTOKEN)
54 auto const next = dir->at(~sfIndexNext);
55 auto const prev = dir->at(~sfIndexPrevious);
56 if ((prev && (*prev != 0u)) || (next && (*next != 0u)))
58 JLOG(j.
fatal()) <<
"Invariant failed: Loan Broker with zero "
59 "OwnerCount has multiple directory pages";
62 auto indexes = dir->getFieldV256(sfIndexes);
63 if (indexes.size() > 1)
65 JLOG(j.
fatal()) <<
"Invariant failed: Loan Broker with zero "
66 "OwnerCount has multiple indexes in the Directory root";
69 if (indexes.size() == 1)
71 auto const index = indexes.value().front();
75 JLOG(j.
fatal()) <<
"Invariant failed: Loan Broker directory corrupt";
78 if (sle->getType() != ltRIPPLE_STATE && sle->getType() != ltMPTOKEN)
80 JLOG(j.
fatal()) <<
"Invariant failed: Loan Broker with zero "
81 "OwnerCount has an unexpected entry in the directory";
100 for (
auto const& line :
lines_)
102 for (
auto const& field : {&sfLowLimit, &sfHighLimit})
108 if (account && account->isFieldPresent(sfLoanBrokerID))
110 auto const& loanBrokerID = account->at(sfLoanBrokerID);
116 for (
auto const& mpt :
mpts_)
122 if (account && account->isFieldPresent(sfLoanBrokerID))
124 auto const& loanBrokerID = account->at(sfLoanBrokerID);
130 for (
auto const& [brokerID, broker] :
brokers_)
137 JLOG(j.
fatal()) <<
"Invariant failed: Loan Broker missing";
141 auto const& before = broker.brokerBefore;
147 if (
after->at(sfOwnerCount) == 0)
158 if (before && before->at(sfLoanSequence) >
after->at(sfLoanSequence))
160 JLOG(j.
fatal()) <<
"Invariant failed: Loan Broker sequence number "
164 if (
after->at(sfDebtTotal) < 0)
166 JLOG(j.
fatal()) <<
"Invariant failed: Loan Broker debt total is negative";
169 if (
after->at(sfCoverAvailable) < 0)
171 JLOG(j.
fatal()) <<
"Invariant failed: Loan Broker cover available is negative";
177 JLOG(j.
fatal()) <<
"Invariant failed: Loan Broker vault ID is invalid";
180 auto const& vaultAsset = vault->at(sfAsset);
183 after->at(sfAccount),
188 if (
after->at(sfCoverAvailable) < pseudoBalance)
190 JLOG(j.
fatal()) <<
"Invariant failed: Loan Broker cover available "
191 "is less than pseudo-account asset balance";
199 if (tx.
getTxnType() != ttLOAN_BROKER_DELETE &&
200 after->at(sfCoverAvailable) > pseudoBalance)
202 JLOG(j.
fatal()) <<
"Invariant failed: Loan Broker cover available is greater "
203 "than pseudo-account asset balance";
A generic endpoint for log messages.
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.
std::shared_ptr< STLedgerEntry const > const & const_ref
TxType getTxnType() const
std::map< uint256, BrokerInfo > brokers_
static bool goodZeroDirectory(ReadView const &view, SLE::const_ref dir, beast::Journal const &j)
void visitEntry(bool, SLE::const_ref, SLE::const_ref)
std::vector< SLE::const_pointer > mpts_
std::vector< SLE::const_pointer > lines_
bool finalize(STTx const &, TER const, XRPAmount const, ReadView const &, beast::Journal const &)
Keylet loanBroker(AccountID const &owner, std::uint32_t seq) noexcept
Keylet unchecked(uint256 const &key) noexcept
Any ledger entry.
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Keylet vault(AccountID const &owner, std::uint32_t seq) noexcept
Keylet account(AccountID const &id) noexcept
AccountID root.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?
TERSubset< CanCvtToTER > TER
STAmount accountHolds(ReadView const &view, AccountID const &account, Currency const ¤cy, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j, SpendableHandling includeFullBalance=SpendableHandling::SimpleBalance)