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>
27 if (
after->getType() == ltLOAN_BROKER)
30 broker.brokerBefore = before;
31 broker.brokerAfter =
after;
33 else if (
after->getType() == ltACCOUNT_ROOT &&
after->isFieldPresent(sfLoanBrokerID))
35 auto const& loanBrokerID =
after->at(sfLoanBrokerID);
39 else if (
after->getType() == ltRIPPLE_STATE)
43 else if (
after->getType() == ltMPTOKEN)
56 auto const next = dir->at(~sfIndexNext);
57 auto const prev = dir->at(~sfIndexPrevious);
58 if ((prev && (*prev != 0u)) || (next && (*next != 0u)))
60 JLOG(j.
fatal()) <<
"Invariant failed: Loan Broker with zero "
61 "OwnerCount has multiple directory pages";
64 auto indexes = dir->getFieldV256(sfIndexes);
65 if (indexes.size() > 1)
67 JLOG(j.
fatal()) <<
"Invariant failed: Loan Broker with zero "
68 "OwnerCount has multiple indexes in the Directory root";
71 if (indexes.size() == 1)
73 auto const index = indexes.value().front();
77 JLOG(j.
fatal()) <<
"Invariant failed: Loan Broker directory corrupt";
80 if (sle->getType() != ltRIPPLE_STATE && sle->getType() != ltMPTOKEN)
82 JLOG(j.
fatal()) <<
"Invariant failed: Loan Broker with zero "
83 "OwnerCount has an unexpected entry in the directory";
102 for (
auto const& line :
lines_)
104 for (
auto const& field : {&sfLowLimit, &sfHighLimit})
110 if (account && account->isFieldPresent(sfLoanBrokerID))
112 auto const& loanBrokerID = account->at(sfLoanBrokerID);
118 for (
auto const& mpt :
mpts_)
124 if (account && account->isFieldPresent(sfLoanBrokerID))
126 auto const& loanBrokerID = account->at(sfLoanBrokerID);
133 auto const& [brokerID, broker] = entry;
139 JLOG(j.
fatal()) <<
"Invariant failed: Loan Broker missing";
143 auto const& before = broker.brokerBefore;
149 if (
after->at(sfOwnerCount) == 0)
160 if (before && before->at(sfLoanSequence) >
after->at(sfLoanSequence))
162 JLOG(j.
fatal()) <<
"Invariant failed: Loan Broker sequence number "
166 if (
after->at(sfDebtTotal) < 0)
168 JLOG(j.
fatal()) <<
"Invariant failed: Loan Broker debt total is negative";
171 if (
after->at(sfCoverAvailable) < 0)
173 JLOG(j.
fatal()) <<
"Invariant failed: Loan Broker cover available is negative";
179 JLOG(j.
fatal()) <<
"Invariant failed: Loan Broker vault ID is invalid";
182 auto const& vaultAsset = vault->at(sfAsset);
185 after->at(sfAccount),
190 if (
after->at(sfCoverAvailable) < pseudoBalance)
192 JLOG(j.
fatal()) <<
"Invariant failed: Loan Broker cover available "
193 "is less than pseudo-account asset balance";
201 if (tx.
getTxnType() != ttLOAN_BROKER_DELETE &&
202 after->at(sfCoverAvailable) > pseudoBalance)
204 JLOG(j.
fatal()) <<
"Invariant failed: Loan Broker cover available is greater "
205 "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 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, SeqProxy const &seq) noexcept
Keylet loanBroker(AccountID const &owner, SeqProxy const &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)