1#include <xrpl/tx/invariants/LoanBrokerInvariant.h>
3#include <xrpl/basics/Log.h>
4#include <xrpl/beast/utility/instrumentation.h>
5#include <xrpl/ledger/View.h>
6#include <xrpl/ledger/helpers/RippleStateHelpers.h>
7#include <xrpl/protocol/Indexes.h>
8#include <xrpl/protocol/LedgerFormats.h>
9#include <xrpl/protocol/STNumber.h>
10#include <xrpl/protocol/TxFormats.h>
22 if (
after->getType() == ltLOAN_BROKER)
25 broker.brokerBefore = before;
26 broker.brokerAfter =
after;
28 else if (
after->getType() == ltACCOUNT_ROOT &&
after->isFieldPresent(sfLoanBrokerID))
30 auto const& loanBrokerID =
after->at(sfLoanBrokerID);
34 else if (
after->getType() == ltRIPPLE_STATE)
38 else if (
after->getType() == ltMPTOKEN)
51 auto const next = dir->at(~sfIndexNext);
52 auto const prev = dir->at(~sfIndexPrevious);
53 if ((prev && (*prev != 0u)) || (next && (*next != 0u)))
55 JLOG(j.
fatal()) <<
"Invariant failed: Loan Broker with zero "
56 "OwnerCount has multiple directory pages";
59 auto indexes = dir->getFieldV256(sfIndexes);
60 if (indexes.size() > 1)
62 JLOG(j.
fatal()) <<
"Invariant failed: Loan Broker with zero "
63 "OwnerCount has multiple indexes in the Directory root";
66 if (indexes.size() == 1)
68 auto const index = indexes.value().front();
72 JLOG(j.
fatal()) <<
"Invariant failed: Loan Broker directory corrupt";
75 if (sle->getType() != ltRIPPLE_STATE && sle->getType() != ltMPTOKEN)
77 JLOG(j.
fatal()) <<
"Invariant failed: Loan Broker with zero "
78 "OwnerCount has an unexpected entry in the directory";
97 for (
auto const& line :
lines_)
99 for (
auto const& field : {&sfLowLimit, &sfHighLimit})
105 if (account && account->isFieldPresent(sfLoanBrokerID))
107 auto const& loanBrokerID = account->at(sfLoanBrokerID);
113 for (
auto const& mpt :
mpts_)
119 if (account && account->isFieldPresent(sfLoanBrokerID))
121 auto const& loanBrokerID = account->at(sfLoanBrokerID);
127 for (
auto const& [brokerID, broker] :
brokers_)
134 JLOG(j.
fatal()) <<
"Invariant failed: Loan Broker missing";
138 auto const& before = broker.brokerBefore;
144 if (
after->at(sfOwnerCount) == 0)
155 if (before && before->at(sfLoanSequence) >
after->at(sfLoanSequence))
157 JLOG(j.
fatal()) <<
"Invariant failed: Loan Broker sequence number "
161 if (
after->at(sfDebtTotal) < 0)
163 JLOG(j.
fatal()) <<
"Invariant failed: Loan Broker debt total is negative";
166 if (
after->at(sfCoverAvailable) < 0)
168 JLOG(j.
fatal()) <<
"Invariant failed: Loan Broker cover available is negative";
174 JLOG(j.
fatal()) <<
"Invariant failed: Loan Broker vault ID is invalid";
177 auto const& vaultAsset = vault->at(sfAsset);
180 after->at(sfAccount),
185 if (
after->at(sfCoverAvailable) < pseudoBalance)
187 JLOG(j.
fatal()) <<
"Invariant failed: Loan Broker cover available "
188 "is less than pseudo-account asset balance";
196 if (tx.
getTxnType() != ttLOAN_BROKER_DELETE &&
197 after->at(sfCoverAvailable) > pseudoBalance)
199 JLOG(j.
fatal()) <<
"Invariant failed: Loan Broker cover available is greater "
200 "than pseudo-account asset balance";
A generic endpoint for log messages.
virtual Rules const & rules() const =0
Returns the tx processing rules.
virtual std::shared_ptr< SLE const > 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.
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, std::shared_ptr< SLE const > const &, std::shared_ptr< SLE const > const &)
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 loanbroker(AccountID const &owner, std::uint32_t seq) noexcept
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.
STAmount accountHolds(ReadView const &view, AccountID const &account, Currency const ¤cy, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j, SpendableHandling includeFullBalance=shSIMPLE_BALANCE)
bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?