20#include <xrpl/basics/Expected.h> 
   21#include <xrpl/basics/Log.h> 
   22#include <xrpl/basics/chrono.h> 
   23#include <xrpl/beast/utility/instrumentation.h> 
   24#include <xrpl/ledger/CredentialHelpers.h> 
   25#include <xrpl/ledger/ReadView.h> 
   26#include <xrpl/ledger/View.h> 
   27#include <xrpl/protocol/Feature.h> 
   28#include <xrpl/protocol/Indexes.h> 
   29#include <xrpl/protocol/LedgerFormats.h> 
   30#include <xrpl/protocol/MPTIssue.h> 
   31#include <xrpl/protocol/Protocol.h> 
   32#include <xrpl/protocol/Quality.h> 
   33#include <xrpl/protocol/TER.h> 
   34#include <xrpl/protocol/TxFlags.h> 
   35#include <xrpl/protocol/digest.h> 
   36#include <xrpl/protocol/st.h> 
   59    auto const& svIndexes = page->getFieldV256(sfIndexes);
 
   61        index <= svIndexes.size(),
 
   62        "ripple::detail::internalDirNext : index inside range");
 
   64    if (index >= svIndexes.size())
 
   66        auto const next = page->getFieldU64(sfIndexNext);
 
   79        XRPL_ASSERT(page, 
"ripple::detail::internalDirNext : non-null root");
 
   89    entry = svIndexes[index++];
 
 
  221    if (issuer != account)
 
 
  258    if (issuer != account)
 
 
  291    for (
auto const& account : accounts)
 
  297    for (
auto const& account : accounts)
 
 
  319    auto const mptIssuance =
 
  321    if (mptIssuance == 
nullptr)
 
  324    auto const issuer = mptIssuance->getAccountID(sfIssuer);
 
  326    if (mptIssuer == 
nullptr)
 
  329        UNREACHABLE(
"ripple::isVaultPseudoAccountFrozen : null MPToken issuer");
 
  334    if (!mptIssuer->isFieldPresent(sfVaultID))
 
  339    if (vault == 
nullptr)
 
  341        UNREACHABLE(
"ripple::isVaultPseudoAccountFrozen : null vault");
 
  346    return isAnyFrozen(view, {issuer, account}, vault->at(sfAsset), depth + 1);
 
 
  361    if (issuer == account)
 
 
  403    auto const allowBalance = [&]() {
 
  411            if (
isFrozen(view, account, currency, issuer) ||
 
  426                else if (sleIssuer->isFieldPresent(sfAMMID))
 
  435                            (*sleAmm)[sfAsset].get<Issue>(),
 
  436                            (*sleAmm)[sfAsset2].get<Issue>()))
 
  449        amount = sle->getFieldAmount(sfBalance);
 
  450        if (account > issuer)
 
  462    JLOG(j.
trace()) << 
"accountHolds:" 
 
  496        amount.
clear(mptIssue);
 
  499        amount.
clear(mptIssue);
 
  502        amount = 
STAmount{mptIssue, sleMpt->getFieldU64(sfMPTAmount)};
 
  512                amount.
clear(mptIssue);
 
  516            auto const sleIssuance =
 
  523                amount.
clear(mptIssue);
 
 
  530[[nodiscard]] STAmount
 
  540        [&](
auto const& value) {
 
  545                return accountHolds(view, account, value, zeroIfFrozen, j);
 
  548                view, account, value, zeroIfFrozen, zeroIfUnauthorized, j);
 
 
  595                    << 
"Account " << *
id << 
" owner count exceeds max!";
 
  608                    << 
"Account " << *
id << 
" owner count set below 0!";
 
  611            XRPL_ASSERT(!
id, 
"ripple::confineOwnerCount : id is not set");
 
 
  630        view.
ownerCountHook(
id, sle->getFieldU32(sfOwnerCount)), ownerCountAdj);
 
  637    auto const fullBalance = sle->getFieldAmount(sfBalance);
 
  642        (balance < reserve) ? 
STAmount{0} : balance - reserve;
 
  644    JLOG(j.
trace()) << 
"accountHolds:" 
  647                    << 
" fullBalance=" << fullBalance.getFullText()
 
  648                    << 
" balance=" << balance.getFullText()
 
  649                    << 
" reserve=" << reserve << 
" ownerCount=" << ownerCount
 
  650                    << 
" ownerCountAdj=" << ownerCountAdj;
 
 
  662        root.type == ltDIR_NODE, 
"ripple::forEachItem : valid root type");
 
  664    if (
root.type != ltDIR_NODE)
 
  671        auto sle = view.
read(pos);
 
  674        for (
auto const& key : sle->getFieldV256(sfIndexes))
 
  676        auto const next = sle->getFieldU64(sfIndexNext);
 
 
  693        root.type == ltDIR_NODE, 
"ripple::forEachItemAfter : valid root type");
 
  695    if (
root.type != ltDIR_NODE)
 
  698    auto currentIndex = 
root;
 
  701    if (
after.isNonZero())
 
  705        if (
auto hintDir = view.
read(hintIndex))
 
  707            for (
auto const& key : hintDir->getFieldV256(sfIndexes))
 
  712                    currentIndex = hintIndex;
 
  721            auto const ownerDir = view.
read(currentIndex);
 
  724            for (
auto const& key : ownerDir->getFieldV256(sfIndexes))
 
  737            auto const uNodeNext = ownerDir->getFieldU64(sfIndexNext);
 
  747            auto const ownerDir = view.
read(currentIndex);
 
  750            for (
auto const& key : ownerDir->getFieldV256(sfIndexes))
 
  753            auto const uNodeNext = ownerDir->getFieldU64(sfIndexNext);
 
 
  766    if (sle && sle->isFieldPresent(sfTransferRate))
 
  767        return Rate{sle->getFieldU32(sfTransferRate)};
 
 
  779        sle && sle->isFieldPresent(sfTransferFee))
 
  780        return Rate{1'000'000'000u + 10'000 * sle->getFieldU16(sfTransferFee)};
 
 
  814        if (hash && (*hash != validLedger.
info().
hash))
 
  816            JLOG(s) << reason << 
" incompatible with valid ledger";
 
  818            JLOG(s) << 
"Hash(VSeq): " << 
to_string(*hash);
 
  830        if (hash && (*hash != testLedger.
info().
hash))
 
  832            JLOG(s) << reason << 
" incompatible preceding ledger";
 
  834            JLOG(s) << 
"Hash(NSeq): " << 
to_string(*hash);
 
  844        JLOG(s) << reason << 
" incompatible ledger";
 
  851        JLOG(s) << 
"Val: " << validLedger.
info().
seq << 
" " 
  854        JLOG(s) << 
"New: " << testLedger.
info().
seq << 
" " 
 
  871    if (testLedger.
info().
seq > validIndex)
 
  878        if (hash && (*hash != validHash))
 
  880            JLOG(s) << reason << 
" incompatible following ledger";
 
  881            JLOG(s) << 
"Hash(VSeq): " << 
to_string(*hash);
 
  887        (validIndex == testLedger.
info().
seq) &&
 
  888        (testLedger.
info().
hash != validHash))
 
  890        JLOG(s) << reason << 
" incompatible ledger";
 
  897        JLOG(s) << 
"Val: " << validIndex << 
" " << 
to_string(validHash);
 
  899        JLOG(s) << 
"New: " << testLedger.
info().
seq << 
" " 
 
  909    auto const sleNode = view.
read(k);
 
  912    if (!sleNode->getFieldV256(sfIndexes).empty())
 
  917    return sleNode->getFieldU64(sfIndexNext) == 0;
 
 
  927        if (sle->isFieldPresent(sfAmendments))
 
  929            auto const& v = sle->getFieldV256(sfAmendments);
 
  930            amendments.insert(v.begin(), v.end());
 
 
  944        if (sle->isFieldPresent(sfMajorities))
 
  947            using d = tp::duration;
 
  949            auto const majorities = sle->getFieldArray(sfMajorities);
 
  951            for (
auto const& m : majorities)
 
  952                ret[m.getFieldH256(sfAmendment)] =
 
  953                    tp(d(m.getFieldU32(sfCloseTime)));
 
 
  964    if (seq > ledger.
seq())
 
  967            << 
"Can't get seq " << seq << 
" from " << ledger.
seq() << 
" future";
 
  970    if (seq == ledger.
seq())
 
  972    if (seq == (ledger.
seq() - 1))
 
  975    if (
int diff = ledger.
seq() - seq; diff <= 256)
 
  982                hashIndex->getFieldU32(sfLastLedgerSequence) ==
 
  984                "ripple::hashOfSeq : matching ledger sequence");
 
  985            STVector256 vec = hashIndex->getFieldV256(sfHashes);
 
  986            if (vec.
size() >= diff)
 
  987                return vec[vec.
size() - diff];
 
  989                << 
"Ledger " << ledger.
seq() << 
" missing hash for " << seq
 
  990                << 
" (" << vec.
size() << 
"," << diff << 
")";
 
  995                << 
"Ledger " << ledger.
seq() << 
":" << ledger.
info().
hash 
  996                << 
" missing normal list";
 
 1000    if ((seq & 0xff) != 0)
 
 1002        JLOG(journal.
debug())
 
 1003            << 
"Can't get seq " << seq << 
" from " << ledger.
seq() << 
" past";
 
 1011        auto const lastSeq = hashIndex->getFieldU32(sfLastLedgerSequence);
 
 1012        XRPL_ASSERT(lastSeq >= seq, 
"ripple::hashOfSeq : minimum last ledger");
 
 1014            (lastSeq & 0xff) == 0, 
"ripple::hashOfSeq : valid last ledger");
 
 1015        auto const diff = (lastSeq - seq) >> 8;
 
 1016        STVector256 vec = hashIndex->getFieldV256(sfHashes);
 
 1017        if (vec.
size() > diff)
 
 1018            return vec[vec.
size() - diff - 1];
 
 1020    JLOG(journal.
warn()) << 
"Can't get seq " << seq << 
" from " << ledger.
seq()
 
 
 1040    XRPL_ASSERT(amount, 
"ripple::adjustOwnerCount : nonzero amount input");
 
 1045    sle->at(sfOwnerCount) = adjusted;
 
 
 1053        (*sle)[sfOwner] = account;
 
 
 1064    object->setFieldU64(sfOwnerNode, *page);
 
 
 1077        rsh(hash.data(), hash.size());
 
 
 1100                "ripple::isPseudoAccount : unable to find account root ledger " 
 1104        auto const& soTemplate = ar->getSOTemplate();
 
 1107        for (
auto const& field : soTemplate)
 
 1112        return pseudoFields;
 
 1114    return pseudoFields;
 
 
 1124    return sleAcct && sleAcct->getType() == ltACCOUNT_ROOT &&
 
 1126            fields.begin(), fields.end(), [&sleAcct](
SField const* sf) -> 
bool {
 
 1127                return sleAcct->isFieldPresent(*sf);
 
 
 1131Expected<std::shared_ptr<SLE>, 
TER>
 
 1134    uint256 const& pseudoOwnerKey,
 
 1135    SField const& ownerField)
 
 1142            [&ownerField](
SField const* sf) -> 
bool {
 
 1143                return *sf == ownerField;
 
 1145        "ripple::createPseudoAccount : valid owner field");
 
 1148    if (accountId == beast::zero)
 
 1153    account->setAccountID(sfAccount, accountId);
 
 1154    account->setFieldAmount(sfBalance, 
STAmount{});
 
 1163    account->setFieldU32(sfSequence, seqno);
 
 1167    account->setFieldU32(
 
 1170    account->setFieldH256(ownerField, pseudoOwnerKey);
 
 
 1227    auto const& issuerId = issue.
getIssuer();
 
 1228    auto const& currency = issue.
currency;
 
 1232    auto const& srcId = issuerId;
 
 1233    auto const& dstId = accountID;
 
 1234    auto const high = srcId > dstId;
 
 1235    auto const index = 
keylet::line(srcId, dstId, currency);
 
 1238    if (!sleDst || !sleSrc)
 
 1243    if (view.
read(index))
 
 1262        STAmount{Issue{currency, noAccount()}},
 
 1263        STAmount{Issue{currency, dstId}},
 
 
 1277    auto const& mptID = mptIssue.
getMptID();
 
 1278    auto const mpt = view.
peek(keylet::mptIssuance(mptID));
 
 1283    if (view.
peek(keylet::mptoken(mptID, accountID)))
 
 
 1293    MPTID const& mptIssuanceID,
 
 1299    auto const sleAcct = view.
peek(keylet::account(account));
 
 1313            auto const mptokenKey = keylet::mptoken(mptIssuanceID, account);
 
 1314            auto const sleMpt = view.
peek(mptokenKey);
 
 1315            if (!sleMpt || (*sleMpt)[sfMPTAmount] != 0)
 
 1319                    keylet::ownerDir(account),
 
 1320                    (*sleMpt)[sfOwnerNode],
 
 1340        std::uint32_t const uOwnerCount = sleAcct->getFieldU32(sfOwnerCount);
 
 1342            (uOwnerCount < 2) ? 
XRPAmount(beast::zero)
 
 1345        if (priorBalance < reserveCreate)
 
 1348        auto const mptokenKey = keylet::mptoken(mptIssuanceID, account);
 
 1350        if (
auto ter = 
dirLink(view, account, mptoken))
 
 1353        (*mptoken)[sfAccount] = account;
 
 1354        (*mptoken)[sfMPTokenIssuanceID] = mptIssuanceID;
 
 1355        (*mptoken)[sfFlags] = 0;
 
 1364    auto const sleMptIssuance = view.
read(keylet::mptIssuance(mptIssuanceID));
 
 1365    if (!sleMptIssuance)
 
 1371    if (account != (*sleMptIssuance)[sfIssuer])
 
 1374    auto const sleMpt = view.
peek(keylet::mptoken(mptIssuanceID, *holderID));
 
 1384        flagsOut &= ~lsfMPTAuthorized;
 
 1390    if (flagsIn != flagsOut)
 
 1391        sleMpt->setFieldU32(sfFlags, flagsOut);
 
 
 1400    bool const bSrcHigh,
 
 1406    bool const bNoRipple,       
 
 1417    JLOG(j.
trace()) << 
"trustCreate: " << to_string(uSrcAccountID) << 
", " 
 1418                    << to_string(uDstAccountID) << 
", " 
 1421    auto const& uLowAccountID = !bSrcHigh ? uSrcAccountID : uDstAccountID;
 
 1422    auto const& uHighAccountID = bSrcHigh ? uSrcAccountID : uDstAccountID;
 
 1425    view.
insert(sleRippleState);
 
 1428        keylet::ownerDir(uLowAccountID),
 
 1429        sleRippleState->key(),
 
 1436        keylet::ownerDir(uHighAccountID),
 
 1437        sleRippleState->key(),
 
 1443    bool const bSetDst = saLimit.
getIssuer() == uDstAccountID;
 
 1444    bool const bSetHigh = bSrcHigh ^ bSetDst;
 
 1446    XRPL_ASSERT(sleAccount, 
"ripple::trustCreate : non-null SLE");
 
 1451        sleAccount->getAccountID(sfAccount) ==
 
 1452            (bSetHigh ? uHighAccountID : uLowAccountID),
 
 1453        "ripple::trustCreate : matching account ID");
 
 1454    auto const slePeer =
 
 1455        view.
peek(keylet::account(bSetHigh ? uLowAccountID : uHighAccountID));
 
 1460    sleRippleState->setFieldU64(sfLowNode, *lowNode);
 
 1461    sleRippleState->setFieldU64(sfHighNode, *highNode);
 
 1463    sleRippleState->setFieldAmount(
 
 1464        bSetHigh ? sfHighLimit : sfLowLimit, saLimit);
 
 1465    sleRippleState->setFieldAmount(
 
 1466        bSetHigh ? sfLowLimit : sfHighLimit,
 
 1468            saBalance.
getCurrency(), bSetDst ? uSrcAccountID : uDstAccountID}));
 
 1471        sleRippleState->setFieldU32(
 
 1472            bSetHigh ? sfHighQualityIn : sfLowQualityIn, uQualityIn);
 
 1475        sleRippleState->setFieldU32(
 
 1476            bSetHigh ? sfHighQualityOut : sfLowQualityOut, uQualityOut);
 
 1503    sleRippleState->setFieldU32(sfFlags, uFlags);
 
 1507    sleRippleState->setFieldAmount(
 
 1508        sfBalance, bSetHigh ? -saBalance : saBalance);
 
 1511        uSrcAccountID, uDstAccountID, saBalance, saBalance.
zeroed());
 
 
 1525        auto const sle = view.
read(keylet::account(accountID));
 
 1529        auto const balance = sle->getFieldAmount(sfBalance);
 
 1530        if (balance.xrp() != 0)
 
 1537    auto const line = view.
peek(keylet::line(accountID, issue));
 
 1540    if (line->at(sfBalance)->iou() != beast::zero)
 
 1547        auto sleLowAccount =
 
 1548            view.
peek(keylet::account(line->at(sfLowLimit)->getIssuer()));
 
 1562        auto sleHighAccount =
 
 1563            view.
peek(keylet::account(line->at(sfHighLimit)->getIssuer()));
 
 1564        if (!sleHighAccount)
 
 1577        line->at(sfLowLimit)->getIssuer(),
 
 1578        line->at(sfHighLimit)->getIssuer(),
 
 
 1589    auto const& mptID = mptIssue.
getMptID();
 
 1590    auto const mptoken = view.
peek(keylet::mptoken(mptID, accountID));
 
 1593    if (mptoken->at(sfMPTAmount) != 0)
 
 
 1615    std::uint64_t uLowNode = sleRippleState->getFieldU64(sfLowNode);
 
 1616    std::uint64_t uHighNode = sleRippleState->getFieldU64(sfHighNode);
 
 1618    JLOG(j.
trace()) << 
"trustDelete: Deleting ripple line: low";
 
 1621            keylet::ownerDir(uLowAccountID),
 
 1623            sleRippleState->key(),
 
 1629    JLOG(j.
trace()) << 
"trustDelete: Deleting ripple line: high";
 
 1632            keylet::ownerDir(uHighAccountID),
 
 1634            sleRippleState->key(),
 
 1640    JLOG(j.
trace()) << 
"trustDelete: Deleting ripple line: state";
 
 1641    view.
erase(sleRippleState);
 
 
 1651    auto offerIndex = sle->key();
 
 1652    auto owner = sle->getAccountID(sfAccount);
 
 1655    uint256 uDirectory = sle->getFieldH256(sfBookDirectory);
 
 1658            keylet::ownerDir(owner),
 
 1659            sle->getFieldU64(sfOwnerNode),
 
 1667            keylet::page(uDirectory),
 
 1668            sle->getFieldU64(sfBookNode),
 
 1675    if (sle->isFieldPresent(sfAdditionalBooks))
 
 1678            sle->isFlag(
lsfHybrid) && sle->isFieldPresent(sfDomainID),
 
 1679            "ripple::offerDelete : should be a hybrid domain offer");
 
 1681        auto const& additionalBookDirs = sle->getFieldArray(sfAdditionalBooks);
 
 1683        for (
auto const& bookDir : additionalBookDirs)
 
 1685            auto const& dirIndex = bookDir.getFieldH256(sfBookDirectory);
 
 1686            auto const& dirNode = bookDir.getFieldU64(sfBookNode);
 
 1689                    keylet::page(dirIndex), dirNode, offerIndex, 
false))
 
 
 1721        !bCheckIssuer || uSenderID == issuer || uReceiverID == issuer,
 
 1722        "ripple::rippleCreditIOU : matching issuer or don't care");
 
 1727        uSenderID != uReceiverID,
 
 1728        "ripple::rippleCreditIOU : sender is not receiver");
 
 1730    bool const bSenderHigh = uSenderID > uReceiverID;
 
 1731    auto const index = keylet::line(uSenderID, uReceiverID, currency);
 
 1735        "ripple::rippleCreditIOU : sender is not XRP");
 
 1738        "ripple::rippleCreditIOU : receiver is not XRP");
 
 1741    if (
auto const sleRippleState = view.
peek(index))
 
 1743        STAmount saBalance = sleRippleState->getFieldAmount(sfBalance);
 
 1748        view.
creditHook(uSenderID, uReceiverID, saAmount, saBalance);
 
 1750        STAmount const saBefore = saBalance;
 
 1752        saBalance -= saAmount;
 
 1754        JLOG(j.
trace()) << 
"rippleCreditIOU: " << to_string(uSenderID) << 
" -> " 
 1755                        << to_string(uReceiverID)
 
 1760        std::uint32_t const uFlags(sleRippleState->getFieldU32(sfFlags));
 
 1761        bool bDelete = 
false;
 
 1765        if (saBefore > beast::zero
 
 1767            && saBalance <= beast::zero
 
 1775                    view.
read(keylet::account(uSenderID))->getFlags() &
 
 1778            !sleRippleState->getFieldAmount(
 
 1779                !bSenderHigh ? sfLowLimit : sfHighLimit)
 
 1781            && !sleRippleState->getFieldU32(
 
 1782                   !bSenderHigh ? sfLowQualityIn : sfHighQualityIn)
 
 1784            && !sleRippleState->getFieldU32(
 
 1785                   !bSenderHigh ? sfLowQualityOut : sfHighQualityOut))
 
 1790                view, view.
peek(keylet::account(uSenderID)), -1, j);
 
 1793            sleRippleState->setFieldU32(
 
 1795                uFlags & (!bSenderHigh ? ~
lsfLowReserve : ~lsfHighReserve));
 
 1798            bDelete = !saBalance  
 
 1807        sleRippleState->setFieldAmount(sfBalance, saBalance);
 
 1815                bSenderHigh ? uReceiverID : uSenderID,
 
 1816                !bSenderHigh ? uReceiverID : uSenderID,
 
 1820        view.
update(sleRippleState);
 
 1824    STAmount const saReceiverLimit(
Issue{currency, uReceiverID});
 
 1829    JLOG(j.
debug()) << 
"rippleCreditIOU: " 
 1831                    << to_string(uSenderID) << 
" -> " << to_string(uReceiverID)
 
 1834    auto const sleAccount = view.
peek(keylet::account(uReceiverID));
 
 
 1871    auto const issuer = saAmount.
getIssuer();
 
 1875        "ripple::rippleSendIOU : neither sender nor receiver is XRP");
 
 1877        uSenderID != uReceiverID,
 
 1878        "ripple::rippleSendIOU : sender is not receiver");
 
 1880    if (uSenderID == issuer || uReceiverID == issuer || issuer == 
noAccount())
 
 1887        saActual = saAmount;
 
 1895    saActual = (waiveFee == WaiveTransferFee::Yes)
 
 1899    JLOG(j.
debug()) << 
"rippleSendIOU> " << to_string(uSenderID) << 
" - > " 
 1900                    << to_string(uReceiverID)
 
 1908        terResult = 
rippleCreditIOU(view, uSenderID, issuer, saActual, 
true, j);
 
 
 1934            "ripple::accountSendIOU : minimum amount and not MPT");
 
 1941    if (!saAmount || (uSenderID == uReceiverID))
 
 1948        JLOG(j.
trace()) << 
"accountSendIOU: " << to_string(uSenderID) << 
" -> " 
 1949                        << to_string(uReceiverID) << 
" : " 
 1953            view, uSenderID, uReceiverID, saAmount, saActual, j, waiveFee);
 
 1964        ? view.
peek(keylet::account(uSenderID))
 
 1967        ? view.
peek(keylet::account(uReceiverID))
 
 1970    if (
auto stream = j.
trace())
 
 1976            sender_bal = sender->getFieldAmount(sfBalance).getFullText();
 
 1979            receiver_bal = receiver->getFieldAmount(sfBalance).getFullText();
 
 1981        stream << 
"accountSendIOU> " << to_string(uSenderID) << 
" (" 
 1982               << sender_bal << 
") -> " << to_string(uReceiverID) << 
" (" 
 1983               << receiver_bal << 
") : " << saAmount.
getFullText();
 
 1988        if (sender->getFieldAmount(sfBalance) < saAmount)
 
 1999            auto const sndBal = sender->getFieldAmount(sfBalance);
 
 2003            sender->setFieldAmount(sfBalance, sndBal - saAmount);
 
 2011        auto const rcvBal = receiver->getFieldAmount(sfBalance);
 
 2012        receiver->setFieldAmount(sfBalance, rcvBal + saAmount);
 
 2018    if (
auto stream = j.
trace())
 
 2024            sender_bal = sender->getFieldAmount(sfBalance).getFullText();
 
 2027            receiver_bal = receiver->getFieldAmount(sfBalance).getFullText();
 
 2029        stream << 
"accountSendIOU< " << to_string(uSenderID) << 
" (" 
 2030               << sender_bal << 
") -> " << to_string(uReceiverID) << 
" (" 
 2031               << receiver_bal << 
") : " << saAmount.
getFullText();
 
 
 2047    auto const issuer = saAmount.
getIssuer();
 
 2048    auto sleIssuance = view.
peek(mptID);
 
 2051    if (uSenderID == issuer)
 
 2053        (*sleIssuance)[sfOutstandingAmount] += saAmount.
mpt().
value();
 
 2054        view.
update(sleIssuance);
 
 2058        auto const mptokenID = keylet::mptoken(mptID.key, uSenderID);
 
 2059        if (
auto sle = view.
peek(mptokenID))
 
 2061            auto const amt = sle->getFieldU64(sfMPTAmount);
 
 2062            auto const pay = saAmount.
mpt().
value();
 
 2065            (*sle)[sfMPTAmount] = amt - pay;
 
 2072    if (uReceiverID == issuer)
 
 2074        auto const outstanding = sleIssuance->getFieldU64(sfOutstandingAmount);
 
 2075        auto const redeem = saAmount.
mpt().
value();
 
 2076        if (outstanding >= redeem)
 
 2078            sleIssuance->setFieldU64(sfOutstandingAmount, outstanding - redeem);
 
 2079            view.
update(sleIssuance);
 
 2086        auto const mptokenID = keylet::mptoken(mptID.key, uReceiverID);
 
 2087        if (
auto sle = view.
peek(mptokenID))
 
 2089            (*sle)[sfMPTAmount] += saAmount.
mpt().
value();
 
 
 2110        uSenderID != uReceiverID,
 
 2111        "ripple::rippleSendMPT : sender is not receiver");
 
 2114    auto const issuer = saAmount.
getIssuer();
 
 2121    if (uSenderID == issuer || uReceiverID == issuer)
 
 2125        if (uSenderID == issuer)
 
 2127            auto const sendAmount = saAmount.
mpt().
value();
 
 2128            auto const maximumAmount =
 
 2130            if (sendAmount > maximumAmount ||
 
 2131                sle->getFieldU64(sfOutstandingAmount) >
 
 2132                    maximumAmount - sendAmount)
 
 2141        saActual = saAmount;
 
 2146    saActual = (waiveFee == WaiveTransferFee::Yes)
 
 2152    JLOG(j.
debug()) << 
"rippleSendMPT> " << to_string(uSenderID) << 
" - > " 
 2153                    << to_string(uReceiverID)
 
 2157    if (
auto const terResult =
 
 
 2176        "ripple::accountSendMPT : minimum amount and MPT");
 
 2181    if (!saAmount || (uSenderID == uReceiverID))
 
 2187        view, uSenderID, uReceiverID, saAmount, saActual, j, waiveFee);
 
 
 2203                    view, uSenderID, uReceiverID, saAmount, j, waiveFee);
 
 2206                    view, uSenderID, uReceiverID, saAmount, j, waiveFee);
 
 
 2225    auto sle = view.
peek(keylet::account(sender));
 
 2230    if (before > beast::zero
 
 2232        && 
after <= beast::zero
 
 2236        && 
static_cast<bool>(
 
 2240        !state->getFieldAmount(!bSenderHigh ? sfLowLimit : sfHighLimit)
 
 2242        && !state->getFieldU32(!bSenderHigh ? sfLowQualityIn : sfHighQualityIn)
 
 2245        !state->getFieldU32(!bSenderHigh ? sfLowQualityOut : sfHighQualityOut))
 
 2254            sfFlags, flags & (!bSenderHigh ? ~
lsfLowReserve : ~lsfHighReserve));
 
 
 2274        "ripple::issueIOU : neither account nor issuer is XRP");
 
 2277    XRPL_ASSERT(issue == amount.
issue(), 
"ripple::issueIOU : matching issue");
 
 2281        issue.
account != account, 
"ripple::issueIOU : not issuer account");
 
 2283    JLOG(j.
trace()) << 
"issueIOU: " << to_string(account) << 
": " 
 2286    bool bSenderHigh = issue.
account > account;
 
 2288    auto const index = keylet::line(issue.
account, account, issue.
currency);
 
 2290    if (
auto state = view.
peek(index))
 
 2292        STAmount final_balance = state->getFieldAmount(sfBalance);
 
 2297        STAmount const start_balance = final_balance;
 
 2299        final_balance -= amount;
 
 2318        state->setFieldAmount(sfBalance, final_balance);
 
 2323                bSenderHigh ? account : issue.
account,
 
 2324                bSenderHigh ? issue.
account : account,
 
 2340    auto const receiverAccount = view.
peek(keylet::account(account));
 
 2341    if (!receiverAccount)
 
 
 2374        "ripple::redeemIOU : neither account nor issuer is XRP");
 
 2377    XRPL_ASSERT(issue == amount.
issue(), 
"ripple::redeemIOU : matching issue");
 
 2381        issue.
account != account, 
"ripple::redeemIOU : not issuer account");
 
 2383    JLOG(j.
trace()) << 
"redeemIOU: " << to_string(account) << 
": " 
 2386    bool bSenderHigh = account > issue.
account;
 
 2391        STAmount final_balance = state->getFieldAmount(sfBalance);
 
 2396        STAmount const start_balance = final_balance;
 
 2398        final_balance -= amount;
 
 2401            view, state, bSenderHigh, account, start_balance, final_balance, j);
 
 2411        state->setFieldAmount(sfBalance, final_balance);
 
 2418                bSenderHigh ? issue.
account : account,
 
 2419                bSenderHigh ? account : issue.
account,
 
 2431    JLOG(j.
fatal()) << 
"redeemIOU: " << to_string(account)
 
 2433                    << 
" but no trust line exists!";
 
 
 2448        from != beast::zero, 
"ripple::transferXRP : nonzero from account");
 
 2449    XRPL_ASSERT(to != beast::zero, 
"ripple::transferXRP : nonzero to account");
 
 2450    XRPL_ASSERT(from != to, 
"ripple::transferXRP : sender is not receiver");
 
 2451    XRPL_ASSERT(amount.
native(), 
"ripple::transferXRP : amount is XRP");
 
 2455    if (!sender || !receiver)
 
 2458    JLOG(j.
trace()) << 
"transferXRP: " << to_string(from) << 
" -> " 
 2459                    << to_string(to) << 
") : " << amount.
getFullText();
 
 2461    if (sender->getFieldAmount(sfBalance) < amount)
 
 2473    sender->setFieldAmount(
 
 2474        sfBalance, sender->getFieldAmount(sfBalance) - amount);
 
 2477    receiver->setFieldAmount(
 
 2478        sfBalance, receiver->getFieldAmount(sfBalance) + amount);
 
 
 2494    auto const trustLine =
 
 2497    if (!trustLine && authType == AuthType::StrongAuth)
 
 2502    if (
auto const issuerAccount = view.
read(keylet::account(issue.
account));
 
 2506            return ((*trustLine)[sfFlags] &
 
 
 2524    auto const mptID = keylet::mptIssuance(mptIssue.
getMptID());
 
 2525    auto const sleIssuance = view.
read(mptID);
 
 2529    auto const mptIssuer = sleIssuance->getAccountID(sfIssuer);
 
 2532    if (mptIssuer == account)  
 
 2541        auto const sleIssuer = view.
read(keylet::account(mptIssuer));
 
 2545        if (sleIssuer->isFieldPresent(sfVaultID))
 
 2547            auto const sleVault =
 
 2548                view.
read(keylet::vault(sleIssuer->getFieldH256(sfVaultID)));
 
 2552            auto const asset = sleVault->at(sfAsset);
 
 2556                            return requireAuth(view, issue, account, authType);
 
 2559                                view, issue, account, authType, depth + 1);
 
 2567    auto const mptokenID = keylet::mptoken(mptID.key, account);
 
 2568    auto const sleToken = view.
read(mptokenID);
 
 2572        (authType == AuthType::StrongAuth || authType == AuthType::Legacy))
 
 2577    auto const maybeDomainID = sleIssuance->at(~sfDomainID);
 
 2582            "ripple::requireAuth : issuance requires authorization");
 
 2584        if (
auto const ter =
 
 2585                credentials::validDomain(view, *maybeDomainID, account);
 
 
 2605    MPTID const& mptIssuanceID,
 
 2610    auto const sleIssuance = view.
read(keylet::mptIssuance(mptIssuanceID));
 
 2616        "ripple::enforceMPTokenAuthorization : authorization required");
 
 2618    if (account == sleIssuance->at(sfIssuer))
 
 2621    auto const keylet = keylet::mptoken(mptIssuanceID, account);
 
 2622    auto const sleToken = view.
read(keylet);  
 
 2623    auto const maybeDomainID = sleIssuance->at(~sfDomainID);
 
 2625    bool const authorizedByDomain = [&]() -> 
bool {
 
 2627        if (!maybeDomainID.has_value())
 
 2638    if (!authorizedByDomain && sleToken == 
nullptr)
 
 2649    else if (!authorizedByDomain && maybeDomainID.has_value())
 
 2656    else if (!authorizedByDomain)
 
 2661            sleToken != 
nullptr && !maybeDomainID.has_value(),
 
 2662            "ripple::enforceMPTokenAuthorization : found MPToken");
 
 2668    else if (authorizedByDomain && sleToken != 
nullptr)
 
 2673            maybeDomainID.has_value(),
 
 2674            "ripple::enforceMPTokenAuthorization : found MPToken for domain");
 
 2677    else if (authorizedByDomain)
 
 2682            maybeDomainID.has_value() && sleToken == 
nullptr,
 
 2683            "ripple::enforceMPTokenAuthorization : new MPToken for domain");
 
 2698        "ripple::enforceMPTokenAuthorization : condition list is incomplete");
 
 
 2710    auto const mptID = keylet::mptIssuance(mptIssue.
getMptID());
 
 2711    auto const sleIssuance = view.
read(mptID);
 
 2717        if (from != (*sleIssuance)[sfIssuer] && to != (*sleIssuance)[sfIssuer])
 
 
 2726    Keylet const& ownerDirKeylet,
 
 2733    unsigned int uDirEntry{0};
 
 2734    uint256 dirEntry{beast::zero};
 
 2737    if (view.
exists(ownerDirKeylet) &&
 
 2738        dirFirst(view, ownerDirKeylet.
key, sleDirNode, uDirEntry, dirEntry))
 
 2742            if (maxNodesToDelete && ++deleted > *maxNodesToDelete)
 
 2746            auto sleItem = view.
peek(keylet::child(dirEntry));
 
 2752                    << 
"DeleteAccount: Directory node in ledger " << view.
seq()
 
 2753                    << 
" has index to object that is missing: " 
 2754                    << to_string(dirEntry);
 
 2760                sleItem->getFieldU16(sfLedgerEntryType))};
 
 2764            auto const [ter, skipEntry] = deleter(nodeType, dirEntry, sleItem);
 
 2786                "ripple::cleanupOnAccountDelete : minimum dir entries");
 
 2791                    << 
"DeleteAccount iterator re-validation failed.";
 
 2795            if (skipEntry == SkipEntry::No)
 
 2799            dirNext(view, ownerDirKeylet.
key, sleDirNode, uDirEntry, dirEntry));
 
 
 2812    if (!sleState || sleState->getType() != ltRIPPLE_STATE)
 
 2816        sleState->getFieldAmount(sfLowLimit).getIssuer(),
 
 2817        sleState->getFieldAmount(sfHighLimit).getIssuer());
 
 2818    auto sleLow = view.
peek(keylet::account(low));
 
 2819    auto sleHigh = view.
peek(keylet::account(high));
 
 2820    if (!sleLow || !sleHigh)
 
 2823    bool const ammLow = sleLow->isFieldPresent(sfAMMID);
 
 2824    bool const ammHigh = sleHigh->isFieldPresent(sfAMMID);
 
 2827    if (ammLow && ammHigh)
 
 2831    if (!ammLow && !ammHigh)
 
 2835    if (ammAccountID && (low != *ammAccountID && high != *ammAccountID))
 
 2838    if (
auto const ter = 
trustDelete(view, sleState, low, high, j);
 
 2842            << 
"deleteAMMTrustLine: failed to delete the trustline.";
 
 2847    if (!(sleState->getFlags() & uFlags))
 
 
 2869                    view, uSenderID, uReceiverID, saAmount, bCheckIssuer, j);
 
 2875                    "ripple::rippleCredit : not checking issuer");
 
 2877                    view, uSenderID, uReceiverID, saAmount, j);
 
 
 2891        "ripple::assetsToSharesDeposit : non-negative assets");
 
 2893        assets.
asset() == vault->at(sfAsset),
 
 2894        "ripple::assetsToSharesDeposit : assets and vault match");
 
 2895    if (assets.
negative() || assets.
asset() != vault->at(sfAsset))
 
 2898    Number const assetTotal = vault->at(sfAssetsTotal);
 
 2899    STAmount shares{vault->at(sfShareMPTID)};
 
 2900    if (assetTotal == 0)
 
 2906    Number const shareTotal = issuance->at(sfOutstandingAmount);
 
 2907    shares = (shareTotal * (assets / assetTotal)).truncate();
 
 
 2919        "ripple::sharesToAssetsDeposit : non-negative shares");
 
 2921        shares.
asset() == vault->at(sfShareMPTID),
 
 2922        "ripple::sharesToAssetsDeposit : shares and vault match");
 
 2923    if (shares.
negative() || shares.
asset() != vault->at(sfShareMPTID))
 
 2926    Number const assetTotal = vault->at(sfAssetsTotal);
 
 2927    STAmount assets{vault->at(sfAsset)};
 
 2928    if (assetTotal == 0)
 
 2932            shares.
exponent() - vault->at(sfScale),
 
 2935    Number const shareTotal = issuance->at(sfOutstandingAmount);
 
 2936    assets = assetTotal * (shares / shareTotal);
 
 
 2949        "ripple::assetsToSharesDeposit : non-negative assets");
 
 2951        assets.
asset() == vault->at(sfAsset),
 
 2952        "ripple::assetsToSharesWithdraw : assets and vault match");
 
 2953    if (assets.
negative() || assets.
asset() != vault->at(sfAsset))
 
 2956    Number assetTotal = vault->at(sfAssetsTotal);
 
 2957    assetTotal -= vault->at(sfLossUnrealized);
 
 2958    STAmount shares{vault->at(sfShareMPTID)};
 
 2959    if (assetTotal == 0)
 
 2961    Number const shareTotal = issuance->at(sfOutstandingAmount);
 
 2962    Number result = shareTotal * (assets / assetTotal);
 
 2963    if (truncate == TruncateShares::yes)
 
 
 2977        "ripple::sharesToAssetsDeposit : non-negative shares");
 
 2979        shares.
asset() == vault->at(sfShareMPTID),
 
 2980        "ripple::sharesToAssetsWithdraw : shares and vault match");
 
 2981    if (shares.
negative() || shares.
asset() != vault->at(sfShareMPTID))
 
 2984    Number assetTotal = vault->at(sfAssetsTotal);
 
 2985    assetTotal -= vault->at(sfLossUnrealized);
 
 2986    STAmount assets{vault->at(sfAsset)};
 
 2987    if (assetTotal == 0)
 
 2989    Number const shareTotal = issuance->at(sfOutstandingAmount);
 
 2990    assets = assetTotal * (shares / shareTotal);
 
 
 3002    auto const mptID = keylet::mptIssuance(mptIssue.getMptID());
 
 3003    auto sleIssuance = view.
peek(mptID);
 
 3006        JLOG(j.
error()) << 
"rippleLockEscrowMPT: MPT issuance not found for " 
 3007                        << mptIssue.getMptID();
 
 3014            << 
"rippleLockEscrowMPT: sender is the issuer, cannot lock MPTs.";
 
 3021        auto const mptokenID = keylet::mptoken(mptID.key, sender);
 
 3022        auto sle = view.
peek(mptokenID);
 
 3026                << 
"rippleLockEscrowMPT: MPToken not found for " << sender;
 
 3030        auto const amt = sle->getFieldU64(sfMPTAmount);
 
 3031        auto const pay = amount.
mpt().
value();
 
 3037                << 
"rippleLockEscrowMPT: insufficient MPTAmount for " 
 3038                << to_string(sender) << 
": " << amt << 
" < " << pay;
 
 3042        (*sle)[sfMPTAmount] = amt - pay;
 
 3045        uint64_t 
const locked = (*sle)[~sfLockedAmount].value_or(0);
 
 3050                << 
"rippleLockEscrowMPT: overflow on locked amount for " 
 3051                << to_string(sender) << 
": " << locked << 
" + " << pay;
 
 3055        if (sle->isFieldPresent(sfLockedAmount))
 
 3056            (*sle)[sfLockedAmount] += pay;
 
 3058            sle->setFieldU64(sfLockedAmount, pay);
 
 3066        uint64_t 
const issuanceEscrowed =
 
 3067            (*sleIssuance)[~sfLockedAmount].value_or(0);
 
 3068        auto const pay = amount.
mpt().
value();
 
 3074            JLOG(j.
error()) << 
"rippleLockEscrowMPT: overflow on issuance " 
 3075                               "locked amount for " 
 3076                            << mptIssue.getMptID() << 
": " << issuanceEscrowed
 
 3081        if (sleIssuance->isFieldPresent(sfLockedAmount))
 
 3082            (*sleIssuance)[sfLockedAmount] += pay;
 
 3084            sleIssuance->setFieldU64(sfLockedAmount, pay);
 
 3086        view.
update(sleIssuance);
 
 
 3102            netAmount == grossAmount,
 
 3103            "ripple::rippleUnlockEscrowMPT : netAmount == grossAmount");
 
 3105    auto const& issuer = netAmount.
getIssuer();
 
 3107    auto const mptID = keylet::mptIssuance(mptIssue.getMptID());
 
 3108    auto sleIssuance = view.
peek(mptID);
 
 3111        JLOG(j.
error()) << 
"rippleUnlockEscrowMPT: MPT issuance not found for " 
 3112                        << mptIssue.getMptID();
 
 3118        if (!sleIssuance->isFieldPresent(sfLockedAmount))
 
 3121                << 
"rippleUnlockEscrowMPT: no locked amount in issuance for " 
 3122                << mptIssue.getMptID();
 
 3126        auto const locked = sleIssuance->getFieldU64(sfLockedAmount);
 
 3127        auto const redeem = grossAmount.
mpt().
value();
 
 3134                << 
"rippleUnlockEscrowMPT: insufficient locked amount for " 
 3135                << mptIssue.getMptID() << 
": " << locked << 
" < " << redeem;
 
 3139        auto const newLocked = locked - redeem;
 
 3141            sleIssuance->makeFieldAbsent(sfLockedAmount);
 
 3143            sleIssuance->setFieldU64(sfLockedAmount, newLocked);
 
 3144        view.
update(sleIssuance);
 
 3147    if (issuer != receiver)
 
 3150        auto const mptokenID = keylet::mptoken(mptID.key, receiver);
 
 3151        auto sle = view.
peek(mptokenID);
 
 3155                << 
"rippleUnlockEscrowMPT: MPToken not found for " << receiver;
 
 3159        auto current = sle->getFieldU64(sfMPTAmount);
 
 3160        auto delta = netAmount.
mpt().
value();
 
 3166                << 
"rippleUnlockEscrowMPT: overflow on MPTAmount for " 
 3167                << to_string(receiver) << 
": " << 
current << 
" + " << delta;
 
 3171        (*sle)[sfMPTAmount] += delta;
 
 3177        auto const outstanding = sleIssuance->getFieldU64(sfOutstandingAmount);
 
 3178        auto const redeem = netAmount.
mpt().
value();
 
 3185                << 
"rippleUnlockEscrowMPT: insufficient outstanding amount for " 
 3186                << mptIssue.getMptID() << 
": " << outstanding << 
" < " 
 3191        sleIssuance->setFieldU64(sfOutstandingAmount, outstanding - redeem);
 
 3192        view.
update(sleIssuance);
 
 3195    if (issuer == sender)
 
 3197        JLOG(j.
error()) << 
"rippleUnlockEscrowMPT: sender is the issuer, " 
 3198                           "cannot unlock MPTs.";
 
 3204        auto const mptokenID = keylet::mptoken(mptID.key, sender);
 
 3205        auto sle = view.
peek(mptokenID);
 
 3209                << 
"rippleUnlockEscrowMPT: MPToken not found for " << sender;
 
 3213        if (!sle->isFieldPresent(sfLockedAmount))
 
 3216                << 
"rippleUnlockEscrowMPT: no locked amount in MPToken for " 
 3217                << to_string(sender);
 
 3221        auto const locked = sle->getFieldU64(sfLockedAmount);
 
 3222        auto const delta = grossAmount.
mpt().
value();
 
 3228                << 
"rippleUnlockEscrowMPT: insufficient locked amount for " 
 3229                << to_string(sender) << 
": " << locked << 
" < " << delta;
 
 3233        auto const newLocked = locked - delta;
 
 3235            sle->makeFieldAbsent(sfLockedAmount);
 
 3237            sle->setFieldU64(sfLockedAmount, newLocked);
 
 3248        auto const outstanding = sleIssuance->getFieldU64(sfOutstandingAmount);
 
 3254                << 
"rippleUnlockEscrowMPT: insufficient outstanding amount for " 
 3255                << mptIssue.getMptID() << 
": " << outstanding << 
" < " << diff;
 
 3259        sleIssuance->setFieldU64(sfOutstandingAmount, outstanding - diff);
 
 3260        view.
update(sleIssuance);
 
 
Provide a light-weight way to check active() before string formatting.
 
A generic endpoint for log messages.
 
static Sink & getNullSink()
Returns a Sink which does nothing.
 
Stream trace() const
Severity stream access functions.
 
Writeable view to a ledger, for applying a transaction.
 
virtual void creditHook(AccountID const &from, AccountID const &to, STAmount const &amount, STAmount const &preCreditBalance)
 
virtual void update(std::shared_ptr< SLE > const &sle)=0
Indicate changes to a peeked SLE.
 
bool dirRemove(Keylet const &directory, std::uint64_t page, uint256 const &key, bool keepRoot)
Remove an entry from a directory.
 
virtual void adjustOwnerCountHook(AccountID const &account, std::uint32_t cur, std::uint32_t next)
 
virtual void insert(std::shared_ptr< SLE > const &sle)=0
Insert a new state SLE.
 
std::optional< std::uint64_t > dirInsert(Keylet const &directory, uint256 const &key, std::function< void(std::shared_ptr< SLE > const &)> const &describe)
Insert an entry to a directory.
 
virtual std::shared_ptr< SLE > peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
 
virtual void erase(std::shared_ptr< SLE > const &sle)=0
Remove a peeked SLE.
 
constexpr value_type const & value() const
 
A currency issued by an account.
 
AccountID const & getIssuer() const
 
constexpr value_type value() const
Returns the underlying value.
 
constexpr MPTID const & getMptID() const
 
std::chrono::time_point< NetClock > time_point
 
std::chrono::duration< rep, period > duration
 
Number truncate() const noexcept
 
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
 
NetClock::time_point parentCloseTime() const
Returns the close time of the previous ledger.
 
virtual std::uint32_t ownerCountHook(AccountID const &account, std::uint32_t count) const
 
virtual STAmount balanceHook(AccountID const &account, AccountID const &issuer, STAmount const &amount) const
 
virtual bool open() const =0
Returns true if this reflects an open ledger.
 
virtual Fees const & fees() const =0
Returns the fees for the base ledger.
 
virtual bool exists(Keylet const &k) const =0
Determine if a state item exists.
 
LedgerIndex seq() const
Returns the sequence number of the base ledger.
 
virtual LedgerInfo const & info() const =0
Returns information about the ledger.
 
virtual Rules const & rules() const =0
Returns the tx processing rules.
 
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
 
constexpr bool holds() const noexcept
 
int exponent() const noexcept
 
Asset const & asset() const
 
constexpr TIss const & get() const
 
void setIssuer(AccountID const &uIssuer)
 
Currency const & getCurrency() const
 
bool negative() const noexcept
 
AccountID const & getIssuer() const
 
Issue const & issue() const
 
std::uint64_t mantissa() const noexcept
 
std::string getFullText() const override
 
bool native() const noexcept
 
STAmount zeroed() const
Returns a zero value with the same issuer and currency.
 
std::shared_ptr< STLedgerEntry > const  & ref
 
T emplace_back(T... args)
 
bool internalDirFirst(V &view, uint256 const &root, std::shared_ptr< N > &page, unsigned int &index, uint256 &entry)
 
bool internalDirNext(V &view, uint256 const &root, std::shared_ptr< N > &page, unsigned int &index, uint256 &entry)
 
Keylet mptoken(MPTID const &issuanceID, AccountID const &holder) noexcept
 
Keylet child(uint256 const &key) noexcept
Any item that can be in an owner dir.
 
Keylet amm(Asset const &issue1, Asset const &issue2) noexcept
AMM entry.
 
Keylet line(AccountID const &id0, AccountID const &id1, Currency const ¤cy) noexcept
The index of a trust line for a given currency.
 
Keylet const & amendments() noexcept
The index of the amendment table.
 
Keylet mptIssuance(std::uint32_t seq, AccountID const &issuer) noexcept
 
Keylet vault(AccountID const &owner, std::uint32_t seq) noexcept
 
Keylet account(AccountID const &id) noexcept
AccountID root.
 
Keylet page(uint256 const &root, std::uint64_t index=0) noexcept
A page in a directory.
 
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
 
Keylet const & skip() noexcept
The index of the "short" skip list.
 
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
 
base_uint< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
 
AccountID const & noAccount()
A placeholder for empty accounts.
 
static bool updateTrustLine(ApplyView &view, SLE::pointer state, bool bSenderHigh, AccountID const &sender, STAmount const &before, STAmount const &after, beast::Journal j)
 
std::uint8_t constexpr maxAssetCheckDepth
Maximum recursion depth for vault shares being put as an asset inside another vault; counted from 0.
 
STAmount accountFunds(ReadView const &view, AccountID const &id, STAmount const &saDefault, FreezeHandling freezeHandling, beast::Journal j)
 
FreezeHandling
Controls the treatment of frozen account balances.
 
bool areCompatible(ReadView const &validLedger, ReadView const &testLedger, beast::Journal::Stream &s, char const *reason)
Return false if the test ledger is provably incompatible with the valid ledger, that is,...
 
bool isXRP(AccountID const &c)
 
AccountID const & xrpAccount()
Compute AccountID from public key.
 
TER rippleLockEscrowMPT(ApplyView &view, AccountID const &uGrantorID, STAmount const &saAmount, beast::Journal j)
 
std::optional< STAmount > sharesToAssetsDeposit(std::shared_ptr< SLE const > const &vault, std::shared_ptr< SLE const > const &issuance, STAmount const &shares)
 
bool isIndividualFrozen(ReadView const &view, AccountID const &account, Currency const ¤cy, AccountID const &issuer)
 
bool canSubtract(STAmount const &amt1, STAmount const &amt2)
Determines if it is safe to subtract one STAmount from another.
 
static TER rippleSendMPT(ApplyView &view, AccountID const &uSenderID, AccountID const &uReceiverID, STAmount const &saAmount, STAmount &saActual, beast::Journal j, WaiveTransferFee waiveFee)
 
bool dirFirst(ApplyView &view, uint256 const &root, std::shared_ptr< SLE > &page, unsigned int &index, uint256 &entry)
 
bool dirNext(ApplyView &view, uint256 const &root, std::shared_ptr< SLE > &page, unsigned int &index, uint256 &entry)
 
bool canAdd(STAmount const &amt1, STAmount const &amt2)
Safely checks if two STAmount values can be added without overflow, underflow, or precision loss.
 
bool isDeepFrozen(ReadView const &view, AccountID const &account, Currency const ¤cy, AccountID const &issuer)
 
std::optional< uint256 > hashOfSeq(ReadView const &ledger, LedgerIndex seq, beast::Journal journal)
Return the hash of a ledger by sequence.
 
std::uint64_t constexpr maxMPTokenAmount
The maximum amount of MPTokenIssuance.
 
TER redeemIOU(ApplyView &view, AccountID const &account, STAmount const &amount, Issue const &issue, beast::Journal j)
 
void adjustOwnerCount(ApplyView &view, std::shared_ptr< SLE > const &sle, std::int32_t amount, beast::Journal j)
Adjust the owner count up or down.
 
std::optional< STAmount > assetsToSharesDeposit(std::shared_ptr< SLE const > const &vault, std::shared_ptr< SLE const > const &issuance, STAmount const &assets)
 
STAmount multiply(STAmount const &amount, Rate const &rate)
 
AuthHandling
Controls the treatment of unauthorized MPT balances.
 
std::function< void(SLE::ref)> describeOwnerDir(AccountID const &account)
 
std::optional< STAmount > assetsToSharesWithdraw(std::shared_ptr< SLE const > const &vault, std::shared_ptr< SLE const > const &issuance, STAmount const &assets, TruncateShares truncate=TruncateShares::no)
 
TER transferXRP(ApplyView &view, AccountID const &from, AccountID const &to, STAmount const &amount, beast::Journal j)
 
@ current
This was a new validation and was added.
 
TER accountSend(ApplyView &view, AccountID const &from, AccountID const &to, STAmount const &saAmount, beast::Journal j, WaiveTransferFee waiveFee=WaiveTransferFee::No)
Calls static accountSendIOU if saAmount represents Issue.
 
bool dirIsEmpty(ReadView const &view, Keylet const &k)
Returns true if the directory is empty.
 
TER cleanupOnAccountDelete(ApplyView &view, Keylet const &ownerDirKeylet, EntryDeleter const &deleter, beast::Journal j, std::optional< std::uint16_t > maxNodesToDelete=std::nullopt)
Cleanup owner directory entries on account delete.
 
bool isFrozen(ReadView const &view, AccountID const &account, Currency const ¤cy, AccountID const &issuer)
 
@ expired
List is expired, but has the largest non-pending sequence seen so far.
 
std::set< uint256 > getEnabledAmendments(ReadView const &view)
 
TER rippleUnlockEscrowMPT(ApplyView &view, AccountID const &uGrantorID, AccountID const &uGranteeID, STAmount const &netAmount, STAmount const &grossAmount, beast::Journal j)
 
TER requireAuth(ReadView const &view, Issue const &issue, AccountID const &account, AuthType authType=AuthType::Legacy)
Check if the account lacks required authorization.
 
std::optional< STAmount > sharesToAssetsWithdraw(std::shared_ptr< SLE const > const &vault, std::shared_ptr< SLE const > const &issuance, STAmount const &shares)
 
void forEachItem(ReadView const &view, Keylet const &root, std::function< void(std::shared_ptr< SLE const > const &)> const &f)
Iterate all items in the given directory.
 
static std::uint32_t confineOwnerCount(std::uint32_t current, std::int32_t adjustment, std::optional< AccountID > const &id=std::nullopt, beast::Journal j=beast::Journal{beast::Journal::getNullSink()})
 
static TER rippleCreditIOU(ApplyView &view, AccountID const &uSenderID, AccountID const &uReceiverID, STAmount const &saAmount, bool bCheckIssuer, beast::Journal j)
 
constexpr std::uint32_t const tfMPTUnauthorize
 
TER canTransfer(ReadView const &view, MPTIssue const &mptIssue, AccountID const &from, AccountID const &to)
Check if the destination account is allowed to receive MPT.
 
Expected< std::shared_ptr< SLE >, TER > createPseudoAccount(ApplyView &view, uint256 const &pseudoOwnerKey, SField const &ownerField)
Create pseudo-account, storing pseudoOwnerKey into ownerField.
 
bool hasExpired(ReadView const &view, std::optional< std::uint32_t > const &exp)
Determines whether the given expiration time has passed.
 
bool isVaultPseudoAccountFrozen(ReadView const &view, AccountID const &account, MPTIssue const &mptShare, int depth)
 
TER issueIOU(ApplyView &view, AccountID const &account, STAmount const &amount, Issue const &issue, beast::Journal j)
 
static TER accountSendIOU(ApplyView &view, AccountID const &uSenderID, AccountID const &uReceiverID, STAmount const &saAmount, beast::Journal j, WaiveTransferFee waiveFee)
 
std::map< uint256, NetClock::time_point > majorityAmendments_t
 
bool forEachItemAfter(ReadView const &view, Keylet const &root, uint256 const &after, std::uint64_t const hint, unsigned int limit, std::function< bool(std::shared_ptr< SLE const > const &)> const &f)
Iterate all items after an item in the given directory.
 
Rate transferRate(ReadView const &view, AccountID const &issuer)
Returns IOU issuer transfer fee as Rate.
 
TER trustDelete(ApplyView &view, std::shared_ptr< SLE > const &sleRippleState, AccountID const &uLowAccountID, AccountID const &uHighAccountID, beast::Journal j)
 
@ tecNO_LINE_INSUF_RESERVE
 
@ tecINSUFFICIENT_RESERVE
 
TER rippleCredit(ApplyView &view, AccountID const &uSenderID, AccountID const &uReceiverID, STAmount const &saAmount, bool bCheckIssuer, beast::Journal j)
Calls static rippleCreditIOU if saAmount represents Issue.
 
TER addEmptyHolding(ApplyView &view, AccountID const &accountID, XRPAmount priorBalance, Issue const &issue, beast::Journal journal)
Any transactors that call addEmptyHolding() in doApply must call canAddHolding() in preflight with th...
 
AccountID pseudoAccountAddress(ReadView const &view, uint256 const &pseudoOwnerKey)
 
STAmount accountHolds(ReadView const &view, AccountID const &account, Currency const ¤cy, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j)
 
bool isLPTokenFrozen(ReadView const &view, AccountID const &account, Issue const &asset, Issue const &asset2)
 
bool isTesSuccess(TER x) noexcept
 
majorityAmendments_t getMajorityAmendments(ReadView const &view)
 
bool cdirFirst(ReadView const &view, uint256 const &root, std::shared_ptr< SLE const > &page, unsigned int &index, uint256 &entry)
Returns the first entry in the directory, advancing the index.
 
std::string to_string(base_uint< Bits, Tag > const &a)
 
LedgerEntryType
Identifiers for on-ledger objects.
 
bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?
 
TER trustCreate(ApplyView &view, bool const bSrcHigh, AccountID const &uSrcAccountID, AccountID const &uDstAccountID, uint256 const &uIndex, SLE::ref sleAccount, bool const bAuth, bool const bNoRipple, bool const bFreeze, bool bDeepFreeze, STAmount const &saBalance, STAmount const &saLimit, std::uint32_t uSrcQualityIn, std::uint32_t uSrcQualityOut, beast::Journal j)
Create a trust line.
 
Number root(Number f, unsigned d)
 
TER verifyValidDomain(ApplyView &view, AccountID const &account, uint256 domainID, beast::Journal j)
 
TER deleteAMMTrustLine(ApplyView &view, std::shared_ptr< SLE > sleState, std::optional< AccountID > const &ammAccountID, beast::Journal j)
Delete trustline to AMM.
 
TER enforceMPTokenAuthorization(ApplyView &view, MPTID const &mptIssuanceID, AccountID const &account, XRPAmount const &priorBalance, beast::Journal j)
Enforce account has MPToken to match its authorization.
 
TER canAddHolding(ReadView const &view, Asset const &asset)
 
bool cdirNext(ReadView const &view, uint256 const &root, std::shared_ptr< SLE const > &page, unsigned int &index, uint256 &entry)
Returns the next entry in the directory, advancing the index.
 
static TER rippleSendIOU(ApplyView &view, AccountID const &uSenderID, AccountID const &uReceiverID, STAmount const &saAmount, STAmount &saActual, beast::Journal j, WaiveTransferFee waiveFee)
 
bool isAnyFrozen(ReadView const &view, std::initializer_list< AccountID > const &accounts, MPTIssue const &mptIssue, int depth=0)
 
std::vector< SField const * > const & getPseudoAccountFields()
 
TER authorizeMPToken(ApplyView &view, XRPAmount const &priorBalance, MPTID const &mptIssuanceID, AccountID const &account, beast::Journal journal, std::uint32_t flags=0, std::optional< AccountID > holderID=std::nullopt)
 
TERSubset< CanCvtToTER > TER
 
sha512_half_hasher::result_type sha512Half(Args const &... args)
Returns the SHA512-Half of a series of objects.
 
TER removeEmptyHolding(ApplyView &view, AccountID const &accountID, Issue const &issue, beast::Journal journal)
 
static TER rippleCreditMPT(ApplyView &view, AccountID const &uSenderID, AccountID const &uReceiverID, STAmount const &saAmount, beast::Journal j)
 
void LogicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
 
TER offerDelete(ApplyView &view, std::shared_ptr< SLE > const &sle, beast::Journal j)
Delete an offer.
 
bool isPseudoAccount(std::shared_ptr< SLE const > sleAcct)
 
static TER accountSendMPT(ApplyView &view, AccountID const &uSenderID, AccountID const &uReceiverID, STAmount const &saAmount, beast::Journal j, WaiveTransferFee waiveFee)
 
TER dirLink(ApplyView &view, AccountID const &owner, std::shared_ptr< SLE > &object)
 
Rate const parityRate
A transfer rate signifying a 1:1 exchange.
 
XRPAmount xrpLiquid(ReadView const &view, AccountID const &id, std::int32_t ownerCountAdj, beast::Journal j)
 
bool isGlobalFrozen(ReadView const &view, AccountID const &issuer)
 
XRPAmount accountReserve(std::size_t ownerCount) const
Returns the account reserve given the owner count, in drops.
 
A pair of SHAMap key and LedgerEntryType.
 
Represents a transfer rate.
 
Returns the RIPEMD-160 digest of the SHA256 hash of the message.
 
T time_since_epoch(T... args)