From ad6e048ab2a582aa4f78d9be9ed7427f2e8770b2 Mon Sep 17 00:00:00 2001 From: Bronek Kozicki Date: Tue, 1 Apr 2025 13:49:58 +0100 Subject: [PATCH] Bring back addEmptyHolding and removeEmptyHolding to View --- src/xrpld/app/tx/detail/VaultCreate.cpp | 71 +-------------- src/xrpld/app/tx/detail/VaultDelete.cpp | 57 +----------- src/xrpld/ledger/View.h | 60 +++++++++++++ src/xrpld/ledger/detail/View.cpp | 114 ++++++++++++++++++++++++ 4 files changed, 176 insertions(+), 126 deletions(-) diff --git a/src/xrpld/app/tx/detail/VaultCreate.cpp b/src/xrpld/app/tx/detail/VaultCreate.cpp index 7d23694787..db2ce83dba 100644 --- a/src/xrpld/app/tx/detail/VaultCreate.cpp +++ b/src/xrpld/app/tx/detail/VaultCreate.cpp @@ -130,70 +130,6 @@ VaultCreate::preclaim(PreclaimContext const& ctx) return tesSUCCESS; } -[[nodiscard]] static TER -addEmptyHolding( - ApplyView& view, - AccountID const& accountID, - XRPAmount priorBalance, - Issue const& issue, - beast::Journal journal) -{ - // Every account can hold XRP. - if (issue.native()) - return tesSUCCESS; - - auto const& issuerId = issue.getIssuer(); - auto const& currency = issue.currency; - if (isGlobalFrozen(view, issuerId)) - return tecFROZEN; - - auto const& srcId = issuerId; - auto const& dstId = accountID; - auto const high = srcId > dstId; - auto const index = keylet::line(srcId, dstId, currency); - auto const sle = view.peek(keylet::account(accountID)); - if (!sle) - return tefINTERNAL; - return trustCreate( - view, - high, - srcId, - dstId, - index.key, - sle, - /*auth=*/false, - /*noRipple=*/true, - /*freeze=*/false, - /*deepFreeze*/ false, - /*balance=*/STAmount{Issue{currency, noAccount()}}, - /*limit=*/STAmount{Issue{currency, dstId}}, - /*qualityIn=*/0, - /*qualityOut=*/0, - journal); -} - -[[nodiscard]] static TER -addEmptyHolding( - ApplyView& view, - AccountID const& accountID, - XRPAmount priorBalance, - MPTIssue const& mptIssue, - beast::Journal journal) -{ - auto const& mptID = mptIssue.getMptID(); - auto const mpt = view.peek(keylet::mptIssuance(mptID)); - if (!mpt) - return tefINTERNAL; - if (mpt->getFlags() & lsfMPTLocked) - return tecLOCKED; - return MPTokenAuthorize::authorize( - view, - journal, - {.priorBalance = priorBalance, - .mptIssuanceID = mptID, - .accountID = accountID}); -} - TER VaultCreate::doApply() { @@ -224,12 +160,7 @@ VaultCreate::doApply() auto pseudoId = pseudo->at(sfAccount); auto asset = tx[sfAsset]; - if (auto ter = std::visit( - [&](TIss const& issue) -> TER { - return addEmptyHolding( - view(), pseudoId, mPriorBalance, issue, j_); - }, - asset.value()); + if (auto ter = addEmptyHolding(view(), pseudoId, mPriorBalance, asset, j_); !isTesSuccess(ter)) return ter; diff --git a/src/xrpld/app/tx/detail/VaultDelete.cpp b/src/xrpld/app/tx/detail/VaultDelete.cpp index 85fda38c26..a9414c7a02 100644 --- a/src/xrpld/app/tx/detail/VaultDelete.cpp +++ b/src/xrpld/app/tx/detail/VaultDelete.cpp @@ -66,56 +66,6 @@ VaultDelete::preclaim(PreclaimContext const& ctx) return tesSUCCESS; } -[[nodiscard]] static TER -removeEmptyHolding( - ApplyView& view, - AccountID const& accountID, - Issue const& issue, - beast::Journal journal) -{ - if (issue.native()) - { - auto const sle = view.read(keylet::account(accountID)); - if (!sle) - return tecINTERNAL; - auto const balance = sle->getFieldAmount(sfBalance); - if (balance.xrp() != 0) - return tecHAS_OBLIGATIONS; - return tesSUCCESS; - } - - // `asset` is an IOU. - auto const line = view.peek(keylet::line(accountID, issue)); - if (!line) - return tecOBJECT_NOT_FOUND; - if (line->at(sfBalance)->iou() != beast::zero) - return tecHAS_OBLIGATIONS; - return trustDelete( - view, - line, - line->at(sfLowLimit)->getIssuer(), - line->at(sfHighLimit)->getIssuer(), - journal); -} - -[[nodiscard]] static TER -removeEmptyHolding( - ApplyView& view, - AccountID const& accountID, - MPTIssue const& mptIssue, - beast::Journal journal) -{ - auto const& mptID = mptIssue.getMptID(); - // `MPTokenAuthorize::authorize` asserts that the balance is 0. - return MPTokenAuthorize::authorize( - view, - journal, - {.priorBalance = {}, - .mptIssuanceID = mptID, - .accountID = accountID, - .flags = tfMPTUnauthorize}); -} - TER VaultDelete::doApply() { @@ -125,12 +75,7 @@ VaultDelete::doApply() // Destroy the asset holding. auto asset = vault->at(sfAsset); - if (auto ter = std::visit( - [&](TIss const& issue) -> TER { - return removeEmptyHolding( - view(), vault->at(sfAccount), issue, j_); - }, - (*asset).value()); + if (auto ter = removeEmptyHolding(view(), vault->at(sfAccount), asset, j_); !isTesSuccess(ter)) return ter; diff --git a/src/xrpld/ledger/View.h b/src/xrpld/ledger/View.h index a71524b4e0..a3db88f890 100644 --- a/src/xrpld/ledger/View.h +++ b/src/xrpld/ledger/View.h @@ -500,6 +500,38 @@ createPseudoAccount( uint256 const& pseudoOwnerKey, PseudoAccountOwnerType type); +[[nodiscard]] TER +addEmptyHolding( + ApplyView& view, + AccountID const& accountID, + XRPAmount priorBalance, + Issue const& issue, + beast::Journal journal); + +[[nodiscard]] TER +addEmptyHolding( + ApplyView& view, + AccountID const& accountID, + XRPAmount priorBalance, + MPTIssue const& mptIssue, + beast::Journal journal); + +[[nodiscard]] inline TER +addEmptyHolding( + ApplyView& view, + AccountID const& accountID, + XRPAmount priorBalance, + Asset const& asset, + beast::Journal journal) +{ + return std::visit( + [&](TIss const& issue) -> TER { + return addEmptyHolding( + view, accountID, priorBalance, issue, journal); + }, + asset.value()); +} + // VFALCO NOTE Both STAmount parameters should just // be "Amount", a unit-less number. // @@ -527,6 +559,34 @@ trustCreate( std::uint32_t uSrcQualityOut, beast::Journal j); +[[nodiscard]] TER +removeEmptyHolding( + ApplyView& view, + AccountID const& accountID, + Issue const& issue, + beast::Journal journal); + +[[nodiscard]] TER +removeEmptyHolding( + ApplyView& view, + AccountID const& accountID, + MPTIssue const& mptIssue, + beast::Journal journal); + +[[nodiscard]] inline TER +removeEmptyHolding( + ApplyView& view, + AccountID const& accountID, + Asset const& asset, + beast::Journal journal) +{ + return std::visit( + [&](TIss const& issue) -> TER { + return removeEmptyHolding(view, accountID, issue, journal); + }, + asset.value()); +} + [[nodiscard]] TER trustDelete( ApplyView& view, diff --git a/src/xrpld/ledger/detail/View.cpp b/src/xrpld/ledger/detail/View.cpp index 9f50cebc09..f0777fcd03 100644 --- a/src/xrpld/ledger/detail/View.cpp +++ b/src/xrpld/ledger/detail/View.cpp @@ -1104,6 +1104,70 @@ createPseudoAccount( return account; } +[[nodiscard]] TER +addEmptyHolding( + ApplyView& view, + AccountID const& accountID, + XRPAmount priorBalance, + Issue const& issue, + beast::Journal journal) +{ + // Every account can hold XRP. + if (issue.native()) + return tesSUCCESS; + + auto const& issuerId = issue.getIssuer(); + auto const& currency = issue.currency; + if (isGlobalFrozen(view, issuerId)) + return tecFROZEN; + + auto const& srcId = issuerId; + auto const& dstId = accountID; + auto const high = srcId > dstId; + auto const index = keylet::line(srcId, dstId, currency); + auto const sle = view.peek(keylet::account(accountID)); + if (!sle) + return tefINTERNAL; + return trustCreate( + view, + high, + srcId, + dstId, + index.key, + sle, + /*auth=*/false, + /*noRipple=*/true, + /*freeze=*/false, + /*deepFreeze*/ false, + /*balance=*/STAmount{Issue{currency, noAccount()}}, + /*limit=*/STAmount{Issue{currency, dstId}}, + /*qualityIn=*/0, + /*qualityOut=*/0, + journal); +} + +[[nodiscard]] TER +addEmptyHolding( + ApplyView& view, + AccountID const& accountID, + XRPAmount priorBalance, + MPTIssue const& mptIssue, + beast::Journal journal) +{ + auto const& mptID = mptIssue.getMptID(); + auto const mpt = view.peek(keylet::mptIssuance(mptID)); + if (!mpt) + return tefINTERNAL; + if (mpt->getFlags() & lsfMPTLocked) + return tecLOCKED; + return MPTokenAuthorize::authorize( + view, + journal, + {.priorBalance = priorBalance, + .mptIssuanceID = mptID, + .accountID = accountID}); +} + TER trustCreate( ApplyView& view, @@ -1223,6 +1287,56 @@ trustCreate( return tesSUCCESS; } +[[nodiscard]] TER +removeEmptyHolding( + ApplyView& view, + AccountID const& accountID, + Issue const& issue, + beast::Journal journal) +{ + if (issue.native()) + { + auto const sle = view.read(keylet::account(accountID)); + if (!sle) + return tecINTERNAL; + auto const balance = sle->getFieldAmount(sfBalance); + if (balance.xrp() != 0) + return tecHAS_OBLIGATIONS; + return tesSUCCESS; + } + + // `asset` is an IOU. + auto const line = view.peek(keylet::line(accountID, issue)); + if (!line) + return tecOBJECT_NOT_FOUND; + if (line->at(sfBalance)->iou() != beast::zero) + return tecHAS_OBLIGATIONS; + return trustDelete( + view, + line, + line->at(sfLowLimit)->getIssuer(), + line->at(sfHighLimit)->getIssuer(), + journal); +} + +[[nodiscard]] TER +removeEmptyHolding( + ApplyView& view, + AccountID const& accountID, + MPTIssue const& mptIssue, + beast::Journal journal) +{ + auto const& mptID = mptIssue.getMptID(); + // `MPTokenAuthorize::authorize` asserts that the balance is 0. + return MPTokenAuthorize::authorize( + view, + journal, + {.priorBalance = {}, + .mptIssuanceID = mptID, + .accountID = accountID, + .flags = tfMPTUnauthorize}); +} + TER trustDelete( ApplyView& view,