From 7900fa9ead784db6e2e744d535159ba276138df9 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Sat, 21 Mar 2026 18:17:10 -0700 Subject: [PATCH] more fixes --- .../xrpl/ledger/helpers/AccountRootHelpers.h | 30 ++++- .../xrpl/ledger/helpers/CredentialHelpers.h | 4 +- include/xrpl/ledger/helpers/WrappedSLEBase.h | 20 +++- include/xrpl/tx/Transactor.h | 4 +- src/libxrpl/ledger/View.cpp | 8 +- .../ledger/helpers/AccountRootHelpers.cpp | 17 ++- .../ledger/helpers/CredentialHelpers.cpp | 9 +- src/libxrpl/ledger/helpers/MPTokenHelpers.cpp | 9 +- .../ledger/helpers/RippleStateHelpers.cpp | 30 ++--- src/libxrpl/ledger/helpers/TokenHelpers.cpp | 32 ++--- src/libxrpl/tx/Transactor.cpp | 110 +++++++++--------- src/libxrpl/tx/invariants/LoanInvariant.cpp | 5 +- src/libxrpl/tx/invariants/VaultInvariant.cpp | 9 +- .../tx/transactors/account/AccountDelete.cpp | 46 ++++---- .../tx/transactors/account/AccountSet.cpp | 59 +++++----- .../tx/transactors/account/SetRegularKey.cpp | 19 +-- .../tx/transactors/account/SignerListSet.cpp | 18 +-- .../tx/transactors/bridge/XChainBridge.cpp | 93 +++++++-------- .../tx/transactors/check/CheckCash.cpp | 36 +++--- .../tx/transactors/check/CheckCreate.cpp | 20 ++-- .../credentials/CredentialAccept.cpp | 4 +- .../credentials/CredentialCreate.cpp | 12 +- .../credentials/CredentialDelete.cpp | 6 +- .../tx/transactors/delegate/DelegateSet.cpp | 10 +- src/libxrpl/tx/transactors/dex/AMMBid.cpp | 17 +-- .../tx/transactors/dex/AMMClawback.cpp | 13 ++- src/libxrpl/tx/transactors/dex/AMMCreate.cpp | 26 +++-- src/libxrpl/tx/transactors/dex/AMMDeposit.cpp | 18 +-- src/libxrpl/tx/transactors/dex/AMMUtils.cpp | 11 +- src/libxrpl/tx/transactors/dex/AMMVote.cpp | 10 +- .../tx/transactors/dex/AMMWithdraw.cpp | 21 ++-- .../tx/transactors/dex/OfferCancel.cpp | 12 +- .../tx/transactors/dex/OfferCreate.cpp | 44 +++---- src/libxrpl/tx/transactors/did/DIDDelete.cpp | 2 +- src/libxrpl/tx/transactors/did/DIDSet.cpp | 6 +- .../tx/transactors/escrow/EscrowCancel.cpp | 2 +- .../tx/transactors/escrow/EscrowCreate.cpp | 34 +++--- .../tx/transactors/escrow/EscrowFinish.cpp | 14 +-- .../tx/transactors/escrow/EscrowHelpers.h | 18 +-- .../lending/LoanBrokerCoverClawback.cpp | 13 ++- .../lending/LoanBrokerCoverDeposit.cpp | 3 +- .../lending/LoanBrokerCoverWithdraw.cpp | 4 +- .../transactors/lending/LoanBrokerDelete.cpp | 16 +-- .../tx/transactors/lending/LoanBrokerSet.cpp | 8 +- .../tx/transactors/lending/LoanPay.cpp | 23 ++-- .../tx/transactors/lending/LoanSet.cpp | 18 +-- .../tx/transactors/nft/NFTokenAcceptOffer.cpp | 17 +-- .../tx/transactors/nft/NFTokenBurn.cpp | 9 +- .../tx/transactors/nft/NFTokenMint.cpp | 22 ++-- .../tx/transactors/nft/NFTokenModify.cpp | 7 +- .../tx/transactors/nft/NFTokenUtils.cpp | 33 +++--- .../tx/transactors/oracle/OracleDelete.cpp | 4 +- .../tx/transactors/oracle/OracleSet.cpp | 12 +- .../tx/transactors/payment/DepositPreauth.cpp | 24 ++-- .../tx/transactors/payment/Payment.cpp | 65 +++++------ .../payment_channel/PaymentChannelClaim.cpp | 13 ++- .../payment_channel/PaymentChannelCreate.cpp | 24 ++-- .../payment_channel/PaymentChannelFund.cpp | 15 +-- .../payment_channel/PaymentChannelHelpers.cpp | 1 - .../PermissionedDomainDelete.cpp | 4 +- .../PermissionedDomainSet.cpp | 8 +- src/libxrpl/tx/transactors/system/Change.cpp | 2 +- .../tx/transactors/system/LedgerStateFix.cpp | 3 +- .../tx/transactors/system/TicketCreate.cpp | 16 +-- src/libxrpl/tx/transactors/token/Clawback.cpp | 12 +- .../tx/transactors/token/MPTokenAuthorize.cpp | 5 +- .../token/MPTokenIssuanceCreate.cpp | 2 +- .../token/MPTokenIssuanceDestroy.cpp | 6 +- src/libxrpl/tx/transactors/token/TrustSet.cpp | 44 +++---- .../tx/transactors/vault/VaultClawback.cpp | 13 ++- .../tx/transactors/vault/VaultCreate.cpp | 12 +- .../tx/transactors/vault/VaultDelete.cpp | 18 +-- .../tx/transactors/vault/VaultDeposit.cpp | 24 ++-- .../tx/transactors/vault/VaultWithdraw.cpp | 18 +-- src/xrpld/app/ledger/detail/LocalTxs.cpp | 7 +- src/xrpld/app/misc/detail/TxQ.cpp | 13 ++- src/xrpld/app/paths/PathRequest.cpp | 9 +- src/xrpld/app/paths/Pathfinder.cpp | 13 ++- src/xrpld/app/paths/detail/BookStep.cpp | 6 +- src/xrpld/app/paths/detail/DirectStep.cpp | 6 +- src/xrpld/app/paths/detail/StepChecks.h | 11 +- .../app/paths/detail/XRPEndpointStep.cpp | 4 +- src/xrpld/rpc/detail/TransactionSign.cpp | 47 ++++---- src/xrpld/rpc/handlers/AMMInfo.cpp | 9 +- src/xrpld/rpc/handlers/AccountInfo.cpp | 45 +++---- src/xrpld/rpc/handlers/DepositAuthorized.cpp | 7 +- src/xrpld/rpc/handlers/NoRippleCheck.cpp | 9 +- src/xrpld/rpc/handlers/Simulate.cpp | 8 +- 88 files changed, 817 insertions(+), 753 deletions(-) diff --git a/include/xrpl/ledger/helpers/AccountRootHelpers.h b/include/xrpl/ledger/helpers/AccountRootHelpers.h index f1981c536e..c8aae1a945 100644 --- a/include/xrpl/ledger/helpers/AccountRootHelpers.h +++ b/include/xrpl/ledger/helpers/AccountRootHelpers.h @@ -71,6 +71,29 @@ public: */ [[nodiscard]] TER checkDestinationAndTag(bool hasDestinationTag) const; + + /** Returns true if and only if sleAcct is a pseudo-account or specific + pseudo-accounts in pseudoFieldFilter. + + Returns false if sleAcct is: + - NOT a pseudo-account OR + - NOT a ltACCOUNT_ROOT OR + - null pointer + */ + [[nodiscard]] bool + isPseudoAccount(std::set const& pseudoFieldFilter = {}) const; + + [[nodiscard]] bool + operator==(AccountRoot const& other) const + { + return id_ == other.id_; + } + + [[nodiscard]] bool + operator==(AccountID const& other) const + { + return id_ == other; + } }; /** @@ -84,7 +107,7 @@ class WritableAccountRoot : public AccountRoot, public WritableSLE { public: WritableAccountRoot(AccountID const& id, ApplyView& view) - : AccountRoot(id, view), WritableSLE(view.peek(keylet::account(id)), view) + : AccountRoot(id, view), WritableSLE(keylet::account(id), view) { } @@ -136,7 +159,10 @@ isPseudoAccount( AccountID const& accountId, std::set const& pseudoFieldFilter = {}) { - return isPseudoAccount(view.read(keylet::account(accountId)), pseudoFieldFilter); + AccountRoot const acct(accountId, view); + if (!acct) + return false; + return acct.isPseudoAccount(pseudoFieldFilter); } /** diff --git a/include/xrpl/ledger/helpers/CredentialHelpers.h b/include/xrpl/ledger/helpers/CredentialHelpers.h index c60bd6c7fa..9a96a13c85 100644 --- a/include/xrpl/ledger/helpers/CredentialHelpers.h +++ b/include/xrpl/ledger/helpers/CredentialHelpers.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -73,8 +74,7 @@ verifyDepositPreauth( STTx const& tx, ApplyView& view, AccountID const& src, - AccountID const& dst, - std::shared_ptr const& sleDst, + AccountRoot const& dst, beast::Journal j); } // namespace xrpl diff --git a/include/xrpl/ledger/helpers/WrappedSLEBase.h b/include/xrpl/ledger/helpers/WrappedSLEBase.h index d9d3817956..a53001a2e4 100644 --- a/include/xrpl/ledger/helpers/WrappedSLEBase.h +++ b/include/xrpl/ledger/helpers/WrappedSLEBase.h @@ -167,18 +167,34 @@ public: applyView_.update(mutableSle_); } + void + newSLE() + { + XRPL_ASSERT(canModify(), "xrpl::WritableSLE::newSLE : can modify"); + mutableSle_ = std::make_shared(key_); + } + protected: // Default constructor is deleted (cannot leave reference uninitialized) WritableSLE() = delete; /** Constructor for read-write context (ApplyView) */ explicit WritableSLE(std::shared_ptr sle, ApplyView& view) - : mutableSle_(std::move(sle)), applyView_(view) + : applyView_(view) + , key_(sle ? Keylet(sle->getType(), sle->key()) : Keylet(ltANY, uint256{})) + , mutableSle_(std::move(sle)) { } + /** Constructor for read-write context (ApplyView) */ + explicit WritableSLE(Keylet const& key, ApplyView& view) + : applyView_(view), key_(key), mutableSle_(applyView_.peek(key)) + { + } + + ApplyView& applyView_; // ApplyView for write contexts (first for init order) + Keylet const key_; std::shared_ptr mutableSle_; // Mutable SLE for write contexts - ApplyView& applyView_; // ApplyView for write contexts }; } // namespace xrpl diff --git a/include/xrpl/tx/Transactor.h b/include/xrpl/tx/Transactor.h index 8d816f60f8..cb916f5d7d 100644 --- a/include/xrpl/tx/Transactor.h +++ b/include/xrpl/tx/Transactor.h @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -113,7 +114,8 @@ protected: beast::WrappedSink sink_; beast::Journal const j_; - AccountID const account_; + AccountID const accountID_; + AccountRoot const account_; XRPAmount preFeeBalance_{}; // Balance before fees. virtual ~Transactor() = default; diff --git a/src/libxrpl/ledger/View.cpp b/src/libxrpl/ledger/View.cpp index 130b638f67..b51a06bb9f 100644 --- a/src/libxrpl/ledger/View.cpp +++ b/src/libxrpl/ledger/View.cpp @@ -57,8 +57,8 @@ isVaultPseudoAccountFrozen( return false; // zero MPToken won't block deletion of MPTokenIssuance auto const issuer = mptIssuance->getAccountID(sfIssuer); - auto const mptIssuer = view.read(keylet::account(issuer)); - if (mptIssuer == nullptr) + auto const mptIssuer = AccountRoot(issuer, view); + if (!mptIssuer.exists()) { // LCOV_EXCL_START UNREACHABLE("xrpl::isVaultPseudoAccountFrozen : null MPToken issuer"); @@ -418,8 +418,8 @@ doWithdraw( } else { - auto dstSle = view.read(keylet::account(dstAcct)); - if (auto err = verifyDepositPreauth(tx, view, senderAcct, dstAcct, dstSle, j)) + auto dst = AccountRoot(dstAcct, view); + if (auto err = verifyDepositPreauth(tx, view, senderAcct, dst, j)) return err; } diff --git a/src/libxrpl/ledger/helpers/AccountRootHelpers.cpp b/src/libxrpl/ledger/helpers/AccountRootHelpers.cpp index 7d03e0f20d..70c51427d8 100644 --- a/src/libxrpl/ledger/helpers/AccountRootHelpers.cpp +++ b/src/libxrpl/ledger/helpers/AccountRootHelpers.cpp @@ -70,7 +70,7 @@ AccountRoot::xrpLiquid(std::int32_t ownerCountAdj, beast::Journal j) const // Pseudo-accounts have no reserve requirement auto const reserve = - isPseudoAccount(sle_) ? XRPAmount{0} : readView_.fees().accountReserve(ownerCount); + isPseudoAccount() ? XRPAmount{0} : readView_.fees().accountReserve(ownerCount); auto const fullBalance = sle_->getFieldAmount(sfBalance); @@ -158,6 +158,21 @@ getPseudoAccountFields() return pseudoFields; } +[[nodiscard]] bool +AccountRoot::isPseudoAccount(std::set const& pseudoFieldFilter) const +{ + auto const& fields = getPseudoAccountFields(); + + // Intentionally use defensive coding here because it's cheap and makes the + // semantics of true return value clean. + return sle_ && sle_->getType() == ltACCOUNT_ROOT && + std::count_if( + fields.begin(), fields.end(), [this, &pseudoFieldFilter](SField const* sf) -> bool { + return sle_->isFieldPresent(*sf) && + (pseudoFieldFilter.empty() || pseudoFieldFilter.contains(sf)); + }) > 0; +} + [[nodiscard]] bool isPseudoAccount( std::shared_ptr sleAcct, diff --git a/src/libxrpl/ledger/helpers/CredentialHelpers.cpp b/src/libxrpl/ledger/helpers/CredentialHelpers.cpp index 6bc1fb8c97..56c669e35a 100644 --- a/src/libxrpl/ledger/helpers/CredentialHelpers.cpp +++ b/src/libxrpl/ledger/helpers/CredentialHelpers.cpp @@ -321,8 +321,7 @@ verifyDepositPreauth( STTx const& tx, ApplyView& view, AccountID const& src, - AccountID const& dst, - std::shared_ptr const& sleDst, + AccountRoot const& dst, beast::Journal j) { // If depositPreauth is enabled, then an account that requires @@ -336,15 +335,15 @@ verifyDepositPreauth( if (credentialsPresent && credentials::removeExpired(view, tx.getFieldV256(sfCredentialIDs), j)) return tecEXPIRED; - if (sleDst && ((sleDst->getFlags() & lsfDepositAuth) != 0u)) + if (dst.exists() && (dst->getFlags() & lsfDepositAuth)) { if (src != dst) { - if (!view.exists(keylet::depositPreauth(dst, src))) + if (!view.exists(keylet::depositPreauth(dst.id(), src))) { return !credentialsPresent ? tecNO_PERMISSION : credentials::authorizedDepositPreauth( - view, tx.getFieldV256(sfCredentialIDs), dst); + view, tx.getFieldV256(sfCredentialIDs), dst.id()); } } } diff --git a/src/libxrpl/ledger/helpers/MPTokenHelpers.cpp b/src/libxrpl/ledger/helpers/MPTokenHelpers.cpp index 43fa2151eb..0f976738f8 100644 --- a/src/libxrpl/ledger/helpers/MPTokenHelpers.cpp +++ b/src/libxrpl/ledger/helpers/MPTokenHelpers.cpp @@ -292,7 +292,7 @@ requireAuth( if (!sleIssuance) return tecOBJECT_NOT_FOUND; - auto const mptIssuer = sleIssuance->getAccountID(sfIssuer); + auto const mptIssuer = AccountRoot(sleIssuance->getAccountID(sfIssuer), view); // issuer is always "authorized" if (mptIssuer == account) // Issuer won't have MPToken @@ -306,13 +306,12 @@ requireAuth( return tecINTERNAL; // LCOV_EXCL_LINE // requireAuth is recursive if the issuer is a vault pseudo-account - auto const sleIssuer = view.read(keylet::account(mptIssuer)); - if (!sleIssuer) + if (!mptIssuer.exists()) return tefINTERNAL; // LCOV_EXCL_LINE - if (sleIssuer->isFieldPresent(sfVaultID)) + if (mptIssuer->isFieldPresent(sfVaultID)) { - auto const sleVault = view.read(keylet::vault(sleIssuer->getFieldH256(sfVaultID))); + auto const sleVault = view.read(keylet::vault(mptIssuer->getFieldH256(sfVaultID))); if (!sleVault) return tefINTERNAL; // LCOV_EXCL_LINE diff --git a/src/libxrpl/ledger/helpers/RippleStateHelpers.cpp b/src/libxrpl/ledger/helpers/RippleStateHelpers.cpp index 23dbb65838..ead3789b2c 100644 --- a/src/libxrpl/ledger/helpers/RippleStateHelpers.cpp +++ b/src/libxrpl/ledger/helpers/RippleStateHelpers.cpp @@ -107,14 +107,14 @@ isFrozen( { if (isXRP(currency)) return false; - auto sle = view.read(keylet::account(issuer)); - if (sle && sle->isFlag(lsfGlobalFreeze)) + auto const issuerRoot = AccountRoot(issuer, view); + if (issuerRoot.exists() && issuerRoot->isFlag(lsfGlobalFreeze)) return true; if (issuer != account) { // Check if the issuer froze the line - sle = view.read(keylet::line(account, issuer, currency)); - if (sle && sle->isFlag((issuer > account) ? lsfHighFreeze : lsfLowFreeze)) + auto const sleLine = view.read(keylet::line(account, issuer, currency)); + if (sleLine && sleLine->isFlag((issuer > account) ? lsfHighFreeze : lsfLowFreeze)) return true; } return false; @@ -211,8 +211,8 @@ trustCreate( XRPL_ASSERT( wrappedAcct->getAccountID(sfAccount) == (bSetHigh ? uHighAccountID : uLowAccountID), "xrpl::trustCreate : matching account ID"); - auto const slePeer = view.peek(keylet::account(bSetHigh ? uLowAccountID : uHighAccountID)); - if (!slePeer) + auto const peer = AccountRoot(bSetHigh ? uLowAccountID : uHighAccountID, view); + if (!peer.exists()) return tecNO_TARGET; // Remember deletion hints. @@ -249,7 +249,7 @@ trustCreate( uFlags |= (bSetHigh ? lsfHighDeepFreeze : lsfLowDeepFreeze); } - if ((slePeer->getFlags() & lsfDefaultRipple) == 0) + if ((peer->getFlags() & lsfDefaultRipple) == 0) { // The other side's default is no rippling uFlags |= (bSetHigh ? lsfLowNoRipple : lsfHighNoRipple); @@ -538,8 +538,8 @@ requireAuth(ReadView const& view, Issue const& issue, AccountID const& account, // If this is a weak or legacy check, or if the account has a line, fail if // auth is required and not set on the line - if (auto const issuerAccount = view.read(keylet::account(issue.account)); - issuerAccount && (*issuerAccount)[sfFlags] & lsfRequireAuth) + auto const issuerAccount = AccountRoot(issue.account, view); + if (issuerAccount.exists() && (*issuerAccount)[sfFlags] & lsfRequireAuth) { if (trustLine) { @@ -562,8 +562,8 @@ canTransfer(ReadView const& view, Issue const& issue, AccountID const& from, Acc auto const& issuerId = issue.getIssuer(); if (issuerId == from || issuerId == to) return tesSUCCESS; - auto const sleIssuer = view.read(keylet::account(issuerId)); - if (sleIssuer == nullptr) + auto const issuer = AccountRoot(issuerId, view); + if (issuer.exists()) return tefINTERNAL; // LCOV_EXCL_LINE auto const isRippleDisabled = [&](AccountID account) -> bool { @@ -575,7 +575,7 @@ canTransfer(ReadView const& view, Issue const& issue, AccountID const& from, Acc bool const issuerHigh = issuerId > account; return line->isFlag(issuerHigh ? lsfHighNoRipple : lsfLowNoRipple); } - return sleIssuer->isFlag(lsfDefaultRipple) == false; + return issuer->isFlag(lsfDefaultRipple) == false; }; // Fail if rippling disabled on both trust lines @@ -655,11 +655,11 @@ removeEmptyHolding( { if (issue.native()) { - auto const sle = view.read(keylet::account(accountID)); - if (!sle) + auto const account = AccountRoot(accountID, view); + if (!account.exists()) return tecINTERNAL; // LCOV_EXCL_LINE - auto const balance = sle->getFieldAmount(sfBalance); + auto const balance = account->getFieldAmount(sfBalance); if (balance.xrp() != 0) return tecHAS_OBLIGATIONS; diff --git a/src/libxrpl/ledger/helpers/TokenHelpers.cpp b/src/libxrpl/ledger/helpers/TokenHelpers.cpp index db6484c42b..1cfb7cba9d 100644 --- a/src/libxrpl/ledger/helpers/TokenHelpers.cpp +++ b/src/libxrpl/ledger/helpers/TokenHelpers.cpp @@ -181,14 +181,14 @@ getLineIfUsable( // we need to check if the associated assets have been frozen if (view.rules().enabled(fixFrozenLPTokenTransfer)) { - auto const sleIssuer = view.read(keylet::account(issuer)); - if (!sleIssuer) + auto const issuerRoot = AccountRoot(issuer, view); + if (!issuerRoot.exists()) { return nullptr; // LCOV_EXCL_LINE } - if (sleIssuer->isFieldPresent(sfAMMID)) + if (issuerRoot->isFieldPresent(sfAMMID)) { - auto const sleAmm = view.read(keylet::amm((*sleIssuer)[sfAMMID])); + auto const sleAmm = view.read(keylet::amm((*issuerRoot)[sfAMMID])); if (!sleAmm || isLPTokenFrozen( @@ -428,12 +428,13 @@ canAddHolding(ReadView const& view, Issue const& issue) { return tesSUCCESS; // No special checks for XRP } + auto const issuer = AccountRoot(issue.getIssuer(), view); - auto const issuer = view.read(keylet::account(issue.getIssuer())); - if (!issuer) + if (!issuer.exists()) { return terNO_ACCOUNT; } + if (!issuer->isFlag(lsfDefaultRipple)) { return terNO_RIPPLE; @@ -576,8 +577,7 @@ rippleCreditIOU( && (uFlags & (!bSenderHigh ? lsfLowReserve : lsfHighReserve)) // Sender reserve is set. && static_cast(uFlags & (!bSenderHigh ? lsfLowNoRipple : lsfHighNoRipple)) != - static_cast( - view.read(keylet::account(uSenderID))->getFlags() & lsfDefaultRipple) && + static_cast(AccountRoot(uSenderID, view)->getFlags() & lsfDefaultRipple) && !(uFlags & (!bSenderHigh ? lsfLowFreeze : lsfHighFreeze)) && !sleRippleState->getFieldAmount(!bSenderHigh ? sfLowLimit : sfHighLimit) // Sender trust limit is 0. @@ -1368,15 +1368,15 @@ transferXRP( XRPL_ASSERT(from != to, "xrpl::transferXRP : sender is not receiver"); XRPL_ASSERT(amount.native(), "xrpl::transferXRP : amount is XRP"); - SLE::pointer const sender = view.peek(keylet::account(from)); - SLE::pointer const receiver = view.peek(keylet::account(to)); - if (!sender || !receiver) + WritableAccountRoot acctSender(from, view); + WritableAccountRoot acctReceiver(to, view); + if (!acctSender || !acctReceiver) return tefINTERNAL; // LCOV_EXCL_LINE JLOG(j.trace()) << "transferXRP: " << to_string(from) << " -> " << to_string(to) << ") : " << amount.getFullText(); - if (sender->getFieldAmount(sfBalance) < amount) + if (acctSender->getFieldAmount(sfBalance) < amount) { // VFALCO Its unfortunate we have to keep // mutating these TER everywhere @@ -1387,11 +1387,11 @@ transferXRP( } // Decrement XRP balance. - sender->setFieldAmount(sfBalance, sender->getFieldAmount(sfBalance) - amount); - view.update(sender); + acctSender->setFieldAmount(sfBalance, acctSender->getFieldAmount(sfBalance) - amount); + acctSender.update(); - receiver->setFieldAmount(sfBalance, receiver->getFieldAmount(sfBalance) + amount); - view.update(receiver); + acctReceiver->setFieldAmount(sfBalance, acctReceiver->getFieldAmount(sfBalance) + amount); + acctReceiver.update(); return tesSUCCESS; } diff --git a/src/libxrpl/tx/Transactor.cpp b/src/libxrpl/tx/Transactor.cpp index ba361cade5..d2c20a7c10 100644 --- a/src/libxrpl/tx/Transactor.cpp +++ b/src/libxrpl/tx/Transactor.cpp @@ -232,7 +232,8 @@ Transactor::Transactor(ApplyContext& ctx) : ctx_(ctx) , sink_(ctx.journal, to_short_string(ctx.tx.getTransactionID()) + " ") , j_(sink_) - , account_(ctx.tx.getAccountID(sfAccount)) + , accountID_(ctx.tx.getAccountID(sfAccount)) + , account_(accountID_, ctx.view()) { } @@ -358,11 +359,11 @@ Transactor::checkFee(PreclaimContext const& ctx, XRPAmount baseFee) return tesSUCCESS; auto const id = ctx.tx.getFeePayer(); - auto const sle = ctx.view.read(keylet::account(id)); - if (!sle) + AccountRoot const acctRoot(id, ctx.view); + if (!acctRoot) return terNO_ACCOUNT; - auto const balance = (*sle)[sfBalance].xrp(); + auto const balance = (*acctRoot)[sfBalance].xrp(); if (balance < feePaid) { @@ -387,17 +388,15 @@ Transactor::payFee() auto const feePaid = ctx_.tx[sfFee].xrp(); auto const feePayer = ctx_.tx.getFeePayer(); - auto const sle = view().peek(keylet::account(feePayer)); - if (!sle) + WritableAccountRoot payerAcct(feePayer, view()); + if (!payerAcct) return tefINTERNAL; // LCOV_EXCL_LINE // Deduct the fee, so it's not available during the transaction. // Will only write the account back if the transaction succeeds. - sle->setFieldAmount(sfBalance, sle->getFieldAmount(sfBalance) - feePaid); - if (feePayer != account_) - view().update(sle); // done in `apply()` for the account - - // VFALCO Should we call view().rawDestroyXRP() here as well? + payerAcct->setFieldAmount(sfBalance, payerAcct->getFieldAmount(sfBalance) - feePaid); + if (feePayer != accountID_) + payerAcct.update(); // done in `apply()` for the account return tesSUCCESS; } @@ -406,9 +405,9 @@ Transactor::checkSeqProxy(ReadView const& view, STTx const& tx, beast::Journal j { auto const id = tx.getAccountID(sfAccount); - auto const sle = view.read(keylet::account(id)); + AccountRoot const acctRoot(id, view); - if (!sle) + if (!acctRoot) { JLOG(j.trace()) << "applyTransaction: delay: source account does not exist " << toBase58(id); @@ -416,7 +415,7 @@ Transactor::checkSeqProxy(ReadView const& view, STTx const& tx, beast::Journal j } SeqProxy const t_seqProx = tx.getSeqProxy(); - SeqProxy const a_seq = SeqProxy::sequence((*sle)[sfSequence]); + SeqProxy const a_seq = SeqProxy::sequence((*acctRoot)[sfSequence]); if (t_seqProx.isSeq()) { @@ -471,9 +470,9 @@ Transactor::checkPriorTxAndLastLedger(PreclaimContext const& ctx) { auto const id = ctx.tx.getAccountID(sfAccount); - auto const sle = ctx.view.read(keylet::account(id)); + AccountRoot const acctRoot(id, ctx.view); - if (!sle) + if (!acctRoot) { JLOG(ctx.j.trace()) << "applyTransaction: delay: source account does not exist " << toBase58(id); @@ -481,7 +480,7 @@ Transactor::checkPriorTxAndLastLedger(PreclaimContext const& ctx) } if (ctx.tx.isFieldPresent(sfAccountTxnID) && - (sle->getFieldH256(sfAccountTxnID) != ctx.tx.getFieldH256(sfAccountTxnID))) + (acctRoot->getFieldH256(sfAccountTxnID) != ctx.tx.getFieldH256(sfAccountTxnID))) return tefWRONG_PRIOR; if (ctx.tx.isFieldPresent(sfLastLedgerSequence) && @@ -507,7 +506,7 @@ Transactor::consumeSeqProxy(SLE::pointer const& sleAccount) sleAccount->setFieldU32(sfSequence, seqProx.value() + 1); return tesSUCCESS; } - return ticketDelete(view(), account_, getTicketIndex(account_, seqProx), j_); + return ticketDelete(view(), accountID_, getTicketIndex(accountID_, seqProx), j_); } // Remove a single Ticket from the ledger. @@ -580,7 +579,7 @@ Transactor::ticketDelete( void Transactor::preCompute() { - XRPL_ASSERT(account_ != beast::zero, "xrpl::Transactor::preCompute : nonzero account"); + XRPL_ASSERT(accountID_ != beast::zero, "xrpl::Transactor::preCompute : nonzero account"); } TER @@ -590,19 +589,19 @@ Transactor::apply() // If the transactor requires a valid account and the transaction doesn't // list one, preflight will have already a flagged a failure. - auto const sle = view().peek(keylet::account(account_)); + WritableAccountRoot acct(accountID_, view()); - // sle must exist except for transactions + // acct must exist except for transactions // that allow zero account. XRPL_ASSERT( - sle != nullptr || account_ == beast::zero, + acct.exists() || accountID_ == beast::zero, "xrpl::Transactor::apply : non-null SLE or zero account"); - if (sle) + if (acct) { - preFeeBalance_ = STAmount{(*sle)[sfBalance]}.xrp(); + preFeeBalance_ = STAmount{(*acct)[sfBalance]}.xrp(); - TER result = consumeSeqProxy(sle); + TER result = consumeSeqProxy(acct.mutableSle()); if (!isTesSuccess(result)) return result; @@ -610,10 +609,10 @@ Transactor::apply() if (!isTesSuccess(result)) return result; - if (sle->isFieldPresent(sfAccountTxnID)) - sle->setFieldH256(sfAccountTxnID, ctx_.tx.getTransactionID()); + if (acct->isFieldPresent(sfAccountTxnID)) + acct->setFieldH256(sfAccountTxnID, ctx_.tx.getTransactionID()); - view().update(sle); + acct.update(); } return doApply(); @@ -628,10 +627,9 @@ Transactor::checkSign( STObject const& sigObject, beast::Journal const j) { + AccountRoot const acctSign(idAccount, view); { - auto const sle = view.read(keylet::account(idAccount)); - - if (view.rules().enabled(featureLendingProtocol) && isPseudoAccount(sle)) + if (view.rules().enabled(featureLendingProtocol) && acctSign.isPseudoAccount()) { // Pseudo-accounts can't sign transactions. This check is gated on // the Lending Protocol amendment because that's the project it was @@ -679,11 +677,10 @@ Transactor::checkSign( // Look up the account. auto const idSigner = pkSigner.empty() ? idAccount : calcAccountID(PublicKey(makeSlice(pkSigner))); - auto const sleAccount = view.read(keylet::account(idAccount)); - if (!sleAccount) + if (!acctSign) return terNO_ACCOUNT; - return checkSingleSign(view, idSigner, idAccount, sleAccount, j); + return checkSingleSign(view, idSigner, idAccount, acctSign.sle(), j); } NotTEC @@ -718,11 +715,11 @@ Transactor::checkBatchSign(PreclaimContext const& ctx) // LCOV_EXCL_STOP auto const idSigner = calcAccountID(PublicKey(makeSlice(pkSigner))); - auto const sleAccount = ctx.view.read(keylet::account(idAccount)); + AccountRoot const acctRoot(idAccount, ctx.view); // A batch can include transactions from an un-created account ONLY // when the account master key is the signer - if (!sleAccount) + if (!acctRoot) { if (idAccount != idSigner) return tefBAD_AUTH; @@ -730,7 +727,7 @@ Transactor::checkBatchSign(PreclaimContext const& ctx) return tesSUCCESS; } - if (ret = checkSingleSign(ctx.view, idSigner, idAccount, sleAccount, ctx.j); + if (ret = checkSingleSign(ctx.view, idSigner, idAccount, acctRoot.sle(), ctx.j); !isTesSuccess(ret)) return ret; } @@ -876,15 +873,15 @@ Transactor::checkMultiSign( // In any of these cases we need to know whether the account is in // the ledger. Determine that now. - auto const sleTxSignerRoot = view.read(keylet::account(txSignerAcctID)); + AccountRoot const acctSigner(txSignerAcctID, view); if (signingAcctIDFromPubKey == txSignerAcctID) { // Either Phantom or Master. Phantoms automatically pass. - if (sleTxSignerRoot) + if (acctSigner) { // Master Key. Account may not have asfDisableMaster set. - std::uint32_t const signerAccountFlags = sleTxSignerRoot->getFieldU32(sfFlags); + std::uint32_t const signerAccountFlags = acctSigner->getFieldU32(sfFlags); if ((signerAccountFlags & lsfDisableMaster) != 0u) { @@ -897,19 +894,19 @@ Transactor::checkMultiSign( { // May be a Regular Key. Let's find out. // Public key must hash to the account's regular key. - if (!sleTxSignerRoot) + if (!acctSigner) { JLOG(j.trace()) << "applyTransaction: Non-phantom signer " "lacks account root."; return tefBAD_SIGNATURE; } - if (!sleTxSignerRoot->isFieldPresent(sfRegularKey)) + if (!acctSigner->isFieldPresent(sfRegularKey)) { JLOG(j.trace()) << "applyTransaction: Account lacks RegularKey."; return tefBAD_SIGNATURE; } - if (signingAcctIDFromPubKey != sleTxSignerRoot->getAccountID(sfRegularKey)) + if (signingAcctIDFromPubKey != acctSigner->getAccountID(sfRegularKey)) { JLOG(j.trace()) << "applyTransaction: Account doesn't match RegularKey."; return tefBAD_SIGNATURE; @@ -1011,18 +1008,25 @@ Transactor::reset(XRPAmount fee) { ctx_.discard(); - auto const txnAcct = view().peek(keylet::account(ctx_.tx.getAccountID(sfAccount))); + WritableAccountRoot txnAcct(ctx_.tx.getAccountID(sfAccount), view()); // The account should never be missing from the ledger. But if it // is missing then we can't very well charge it a fee, can we? if (!txnAcct) return {tefINTERNAL, beast::zero}; - auto const payerSle = view().peek(keylet::account(ctx_.tx.getFeePayer())); - if (!payerSle) - return {tefINTERNAL, beast::zero}; // LCOV_EXCL_LINE + auto const feePayer = ctx_.tx.getFeePayer(); + bool const hasDelegateAcct = (feePayer != accountID_); + std::optional delegateAcct; + if (hasDelegateAcct) + { + delegateAcct.emplace(feePayer, view()); + if (!*delegateAcct) + return {tefINTERNAL, beast::zero}; // LCOV_EXCL_LINE + } - auto const balance = payerSle->getFieldAmount(sfBalance).xrp(); + auto& payer = hasDelegateAcct ? *delegateAcct : txnAcct; + auto const balance = payer->getFieldAmount(sfBalance).xrp(); // balance should have already been checked in checkFee / preFlight. XRPL_ASSERT( @@ -1041,15 +1045,15 @@ Transactor::reset(XRPAmount fee) // If for some reason we are unable to consume the ticket or sequence // then the ledger is corrupted. Rather than make things worse we // reject the transaction. - payerSle->setFieldAmount(sfBalance, balance - fee); - TER const ter{consumeSeqProxy(txnAcct)}; + payer->setFieldAmount(sfBalance, balance - fee); + TER const ter{consumeSeqProxy(txnAcct.mutableSle())}; XRPL_ASSERT(isTesSuccess(ter), "xrpl::Transactor::reset : result is tesSUCCESS"); if (isTesSuccess(ter)) { - view().update(txnAcct); - if (payerSle != txnAcct) - view().update(payerSle); + txnAcct.update(); + if (hasDelegateAcct) + delegateAcct->update(); } return {ter, fee}; diff --git a/src/libxrpl/tx/invariants/LoanInvariant.cpp b/src/libxrpl/tx/invariants/LoanInvariant.cpp index c0ce320846..61e505dc77 100644 --- a/src/libxrpl/tx/invariants/LoanInvariant.cpp +++ b/src/libxrpl/tx/invariants/LoanInvariant.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -98,7 +99,7 @@ ValidLoanBroker::finalize( { for (auto const& field : {&sfLowLimit, &sfHighLimit}) { - auto const account = view.read(keylet::account(line->at(*field).getIssuer())); + AccountRoot const account(line->at(*field).getIssuer(), view); // This Invariant doesn't know about the rules for Trust Lines, so // if the account is missing, don't treat it as an error. This // loop is only concerned with finding Broker pseudo-accounts @@ -112,7 +113,7 @@ ValidLoanBroker::finalize( } for (auto const& mpt : mpts_) { - auto const account = view.read(keylet::account(mpt->at(sfAccount))); + AccountRoot const account(mpt->at(sfAccount), view); // This Invariant doesn't know about the rules for MPTokens, so // if the account is missing, don't treat is as an error. This // loop is only concerned with finding Broker pseudo-accounts diff --git a/src/libxrpl/tx/invariants/VaultInvariant.cpp b/src/libxrpl/tx/invariants/VaultInvariant.cpp index f0dd82c2f8..044bac6f10 100644 --- a/src/libxrpl/tx/invariants/VaultInvariant.cpp +++ b/src/libxrpl/tx/invariants/VaultInvariant.cpp @@ -481,16 +481,15 @@ ValidVault::finalize( result = false; } - auto const sleSharesIssuer = - view.read(keylet::account(updatedShares->share.getIssuer())); - if (!sleSharesIssuer) + AccountRoot const acctSharesIssuer(updatedShares->share.getIssuer(), view); + if (!acctSharesIssuer) { JLOG(j.fatal()) // << "Invariant failed: shares issuer must exist"; return false; } - if (!isPseudoAccount(sleSharesIssuer)) + if (!acctSharesIssuer.isPseudoAccount()) { JLOG(j.fatal()) // << "Invariant failed: shares issuer must be a " @@ -498,7 +497,7 @@ ValidVault::finalize( result = false; } - if (auto const vaultId = (*sleSharesIssuer)[~sfVaultID]; + if (auto const vaultId = acctSharesIssuer->at(~sfVaultID); !vaultId || *vaultId != afterVault.key) { JLOG(j.fatal()) // diff --git a/src/libxrpl/tx/transactors/account/AccountDelete.cpp b/src/libxrpl/tx/transactors/account/AccountDelete.cpp index 8c2f23b754..ce8b334767 100644 --- a/src/libxrpl/tx/transactors/account/AccountDelete.cpp +++ b/src/libxrpl/tx/transactors/account/AccountDelete.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -208,12 +209,12 @@ AccountDelete::preclaim(PreclaimContext const& ctx) AccountID const account{ctx.tx[sfAccount]}; AccountID const dst{ctx.tx[sfDestination]}; - auto sleDst = ctx.view.read(keylet::account(dst)); + AccountRoot const acctDst(dst, ctx.view); - if (!sleDst) + if (!acctDst) return tecNO_DST; - if ((((*sleDst)[sfFlags] & lsfRequireDestTag) != 0u) && !ctx.tx[~sfDestinationTag]) + if (acctDst->getFlags() & lsfRequireDestTag && !ctx.tx[~sfDestinationTag]) return tecDST_TAG_NEEDED; // If credentials are provided - check them anyway @@ -225,21 +226,21 @@ AccountDelete::preclaim(PreclaimContext const& ctx) if (!ctx.tx.isFieldPresent(sfCredentialIDs)) { // Check whether the destination account requires deposit authorization. - if ((sleDst->getFlags() & lsfDepositAuth) != 0u) + if (acctDst->getFlags() & lsfDepositAuth) { if (!ctx.view.exists(keylet::depositPreauth(dst, account))) return tecNO_PERMISSION; } } - auto sleAccount = ctx.view.read(keylet::account(account)); - XRPL_ASSERT(sleAccount, "xrpl::AccountDelete::preclaim : non-null account"); - if (!sleAccount) + AccountRoot const acctSrc(account, ctx.view); + XRPL_ASSERT(acctSrc, "xrpl::AccountDelete::preclaim : non-null account"); + if (!acctSrc) return terNO_ACCOUNT; // If an issuer has any issued NFTs resident in the ledger then it // cannot be deleted. - if ((*sleAccount)[~sfMintedNFTokens] != (*sleAccount)[~sfBurnedNFTokens]) + if (acctSrc->at(~sfMintedNFTokens) != acctSrc->at(~sfBurnedNFTokens)) return tecHAS_OBLIGATIONS; // If the account owns any NFTs it cannot be deleted. @@ -258,7 +259,7 @@ AccountDelete::preclaim(PreclaimContext const& ctx) // We look at the account's Sequence rather than the transaction's // Sequence in preparation for Tickets. constexpr std::uint32_t seqDelta{255}; - if ((*sleAccount)[sfSequence] + seqDelta > ctx.view.seq()) + if (acctSrc->getFieldU32(sfSequence) + seqDelta > ctx.view.seq()) return tecTOO_SOON; // We don't allow an account to be deleted if @@ -272,8 +273,8 @@ AccountDelete::preclaim(PreclaimContext const& ctx) // their account and mints a NFToken, it is possible that the // NFTokenSequence of this NFToken is the same as the one that the // authorized minter minted in a previous ledger. - if ((*sleAccount)[~sfFirstNFTokenSequence].value_or(0) + - (*sleAccount)[~sfMintedNFTokens].value_or(0) + seqDelta > + if (acctSrc->at(~sfFirstNFTokenSequence).value_or(0) + + acctSrc->at(~sfMintedNFTokens).value_or(0) + seqDelta > ctx.view.seq()) return tecTOO_SOON; @@ -326,25 +327,24 @@ AccountDelete::preclaim(PreclaimContext const& ctx) TER AccountDelete::doApply() { - auto src = view().peek(keylet::account(account_)); - XRPL_ASSERT(src, "xrpl::AccountDelete::doApply : non-null source account"); + WritableAccountRoot src(accountID_, view()); + XRPL_ASSERT(src.exists(), "xrpl::AccountDelete::doApply : non-null source account"); auto const dstID = ctx_.tx[sfDestination]; - auto dst = view().peek(keylet::account(dstID)); - XRPL_ASSERT(dst, "xrpl::AccountDelete::doApply : non-null destination account"); + WritableAccountRoot dst(dstID, view()); + XRPL_ASSERT(dst.exists(), "xrpl::AccountDelete::doApply : non-null destination account"); - if (!src || !dst) + if (!src.exists() || !dst.exists()) return tefBAD_LEDGER; // LCOV_EXCL_LINE if (ctx_.tx.isFieldPresent(sfCredentialIDs)) { - if (auto err = - verifyDepositPreauth(ctx_.tx, ctx_.view(), account_, dstID, dst, ctx_.journal); + if (auto err = verifyDepositPreauth(ctx_.tx, ctx_.view(), accountID_, dst, ctx_.journal); !isTesSuccess(err)) return err; } - Keylet const ownerDirKeylet{keylet::ownerDir(account_)}; + Keylet const ownerDirKeylet{keylet::ownerDir(accountID_)}; auto const ter = cleanupOnAccountDelete( view(), ownerDirKeylet, @@ -353,7 +353,7 @@ AccountDelete::doApply() std::shared_ptr& sleItem) -> std::pair { if (auto deleter = nonObligationDeleter(nodeType)) { - TER const result{deleter(ctx_.registry, view(), account_, dirEntry, sleItem, j_)}; + TER const result{deleter(ctx_.registry, view(), accountID_, dirEntry, sleItem, j_)}; return {result, SkipEntry::No}; } @@ -384,7 +384,7 @@ AccountDelete::doApply() // delete it. if (view().exists(ownerDirKeylet) && !view().emptyDirDelete(ownerDirKeylet)) { - JLOG(j_.error()) << "AccountDelete cannot delete root dir node of " << toBase58(account_); + JLOG(j_.error()) << "AccountDelete cannot delete root dir node of " << toBase58(accountID_); return tecHAS_OBLIGATIONS; } @@ -392,8 +392,8 @@ AccountDelete::doApply() if (remainingBalance > XRPAmount(0) && dst->isFlag(lsfPasswordSpent)) dst->clearFlag(lsfPasswordSpent); - view().update(dst); - view().erase(src); + dst.update(); + src.erase(); return tesSUCCESS; } diff --git a/src/libxrpl/tx/transactors/account/AccountSet.cpp b/src/libxrpl/tx/transactors/account/AccountSet.cpp index d99324f802..da06e1d37b 100644 --- a/src/libxrpl/tx/transactors/account/AccountSet.cpp +++ b/src/libxrpl/tx/transactors/account/AccountSet.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -208,11 +209,11 @@ AccountSet::preclaim(PreclaimContext const& ctx) std::uint32_t const uTxFlags = ctx.tx.getFlags(); - auto const sle = ctx.view.read(keylet::account(id)); - if (!sle) + AccountRoot const acctRoot(id, ctx.view); + if (!acctRoot) return terNO_ACCOUNT; - std::uint32_t const uFlagsIn = sle->getFieldU32(sfFlags); + std::uint32_t const uFlagsIn = acctRoot->getFieldU32(sfFlags); std::uint32_t const uSetFlag = ctx.tx.getFieldU32(sfSetFlag); @@ -267,11 +268,11 @@ AccountSet::preclaim(PreclaimContext const& ctx) TER AccountSet::doApply() { - auto const sle = view().peek(keylet::account(account_)); - if (!sle) + WritableAccountRoot acct(accountID_, view()); + if (!acct) return tefINTERNAL; // LCOV_EXCL_LINE - std::uint32_t const uFlagsIn = sle->getFieldU32(sfFlags); + std::uint32_t const uFlagsIn = acct->getFieldU32(sfFlags); std::uint32_t uFlagsOut = uFlagsIn; STTx const& tx{ctx_.tx}; @@ -290,7 +291,7 @@ AccountSet::doApply() bool const bSetDisallowXRP{((uTxFlags & tfDisallowXRP) != 0u) || (uSetFlag == asfDisallowXRP)}; bool const bClearDisallowXRP{((uTxFlags & tfAllowXRP) != 0u) || (uClearFlag == asfDisallowXRP)}; - bool const sigWithMaster{[&tx, &acct = account_]() { + bool const sigWithMaster{[&tx, &acct = accountID_]() { auto const spk = tx.getSigningPubKey(); if (publicKeyType(makeSlice(spk))) @@ -359,7 +360,7 @@ AccountSet::doApply() return tecNEED_MASTER_KEY; } - if ((!sle->isFieldPresent(sfRegularKey)) && (!view().peek(keylet::signers(account_)))) + if ((!acct->isFieldPresent(sfRegularKey)) && (!view().peek(keylet::signers(accountID_)))) { // Account has no regular key or multi-signer signer list. return tecNO_ALTERNATIVE_KEY; @@ -424,16 +425,16 @@ AccountSet::doApply() // // Track transaction IDs signed by this account in its root // - if ((uSetFlag == asfAccountTxnID) && !sle->isFieldPresent(sfAccountTxnID)) + if ((uSetFlag == asfAccountTxnID) && !acct->isFieldPresent(sfAccountTxnID)) { JLOG(j_.trace()) << "Set AccountTxnID."; - sle->makeFieldPresent(sfAccountTxnID); + acct->makeFieldPresent(sfAccountTxnID); } - if ((uClearFlag == asfAccountTxnID) && sle->isFieldPresent(sfAccountTxnID)) + if ((uClearFlag == asfAccountTxnID) && acct->isFieldPresent(sfAccountTxnID)) { JLOG(j_.trace()) << "Clear AccountTxnID."; - sle->makeFieldAbsent(sfAccountTxnID); + acct->makeFieldAbsent(sfAccountTxnID); } // @@ -460,12 +461,12 @@ AccountSet::doApply() if (!uHash) { JLOG(j_.trace()) << "unset email hash"; - sle->makeFieldAbsent(sfEmailHash); + acct->makeFieldAbsent(sfEmailHash); } else { JLOG(j_.trace()) << "set email hash"; - sle->setFieldH128(sfEmailHash, uHash); + acct->setFieldH128(sfEmailHash, uHash); } } @@ -479,12 +480,12 @@ AccountSet::doApply() if (!uHash) { JLOG(j_.trace()) << "unset wallet locator"; - sle->makeFieldAbsent(sfWalletLocator); + acct->makeFieldAbsent(sfWalletLocator); } else { JLOG(j_.trace()) << "set wallet locator"; - sle->setFieldH256(sfWalletLocator, uHash); + acct->setFieldH256(sfWalletLocator, uHash); } } @@ -498,12 +499,12 @@ AccountSet::doApply() if (messageKey.empty()) { JLOG(j_.debug()) << "clear message key"; - sle->makeFieldAbsent(sfMessageKey); + acct->makeFieldAbsent(sfMessageKey); } else { JLOG(j_.debug()) << "set message key"; - sle->setFieldVL(sfMessageKey, messageKey); + acct->setFieldVL(sfMessageKey, messageKey); } } @@ -517,12 +518,12 @@ AccountSet::doApply() if (domain.empty()) { JLOG(j_.trace()) << "unset domain"; - sle->makeFieldAbsent(sfDomain); + acct->makeFieldAbsent(sfDomain); } else { JLOG(j_.trace()) << "set domain"; - sle->setFieldVL(sfDomain, domain); + acct->setFieldVL(sfDomain, domain); } } @@ -536,12 +537,12 @@ AccountSet::doApply() if (uRate == 0 || uRate == QUALITY_ONE) { JLOG(j_.trace()) << "unset transfer rate"; - sle->makeFieldAbsent(sfTransferRate); + acct->makeFieldAbsent(sfTransferRate); } else { JLOG(j_.trace()) << "set transfer rate"; - sle->setFieldU32(sfTransferRate, uRate); + acct->setFieldU32(sfTransferRate, uRate); } } @@ -554,21 +555,21 @@ AccountSet::doApply() if ((uTickSize == 0) || (uTickSize == Quality::maxTickSize)) { JLOG(j_.trace()) << "unset tick size"; - sle->makeFieldAbsent(sfTickSize); + acct->makeFieldAbsent(sfTickSize); } else { JLOG(j_.trace()) << "set tick size"; - sle->setFieldU8(sfTickSize, uTickSize); + acct->setFieldU8(sfTickSize, uTickSize); } } // Configure authorized minting account: if (uSetFlag == asfAuthorizedNFTokenMinter) - sle->setAccountID(sfNFTokenMinter, ctx_.tx[sfNFTokenMinter]); + acct->setAccountID(sfNFTokenMinter, ctx_.tx[sfNFTokenMinter]); - if (uClearFlag == asfAuthorizedNFTokenMinter && sle->isFieldPresent(sfNFTokenMinter)) - sle->makeFieldAbsent(sfNFTokenMinter); + if (uClearFlag == asfAuthorizedNFTokenMinter && acct->isFieldPresent(sfNFTokenMinter)) + acct->makeFieldAbsent(sfNFTokenMinter); if (uSetFlag == asfDisallowIncomingNFTokenOffer) { @@ -627,9 +628,9 @@ AccountSet::doApply() } if (uFlagsIn != uFlagsOut) - sle->setFieldU32(sfFlags, uFlagsOut); + acct->setFieldU32(sfFlags, uFlagsOut); - ctx_.view().update(sle); + acct.update(); return tesSUCCESS; } diff --git a/src/libxrpl/tx/transactors/account/SetRegularKey.cpp b/src/libxrpl/tx/transactors/account/SetRegularKey.cpp index 471da26c88..5394f038df 100644 --- a/src/libxrpl/tx/transactors/account/SetRegularKey.cpp +++ b/src/libxrpl/tx/transactors/account/SetRegularKey.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -15,9 +16,9 @@ SetRegularKey::calculateBaseFee(ReadView const& view, STTx const& tx) { if (calcAccountID(PublicKey(makeSlice(spk))) == id) { - auto const sle = view.read(keylet::account(id)); + AccountRoot const acct(id, view); - if (sle && ((sle->getFlags() & lsfPasswordSpent) == 0u)) + if (acct && (!(acct->getFlags() & lsfPasswordSpent))) { // flag is armed and they signed with the right account return XRPAmount{0}; @@ -43,27 +44,27 @@ SetRegularKey::preflight(PreflightContext const& ctx) TER SetRegularKey::doApply() { - auto const sle = view().peek(keylet::account(account_)); - if (!sle) + WritableAccountRoot acct(accountID_, view()); + if (!acct) return tefINTERNAL; // LCOV_EXCL_LINE if (!minimumFee(ctx_.registry, ctx_.baseFee, view().fees(), view().flags())) - sle->setFlag(lsfPasswordSpent); + acct->setFlag(lsfPasswordSpent); if (ctx_.tx.isFieldPresent(sfRegularKey)) { - sle->setAccountID(sfRegularKey, ctx_.tx.getAccountID(sfRegularKey)); + acct->setAccountID(sfRegularKey, ctx_.tx.getAccountID(sfRegularKey)); } else { // Account has disabled master key and no multi-signer signer list. - if (sle->isFlag(lsfDisableMaster) && !view().peek(keylet::signers(account_))) + if (acct->isFlag(lsfDisableMaster) && !view().peek(keylet::signers(accountID_))) return tecNO_ALTERNATIVE_KEY; - sle->makeFieldAbsent(sfRegularKey); + acct->makeFieldAbsent(sfRegularKey); } - ctx_.view().update(sle); + acct.update(); return tesSUCCESS; } diff --git a/src/libxrpl/tx/transactors/account/SignerListSet.cpp b/src/libxrpl/tx/transactors/account/SignerListSet.cpp index 3353b3520f..ee561c3470 100644 --- a/src/libxrpl/tx/transactors/account/SignerListSet.cpp +++ b/src/libxrpl/tx/transactors/account/SignerListSet.cpp @@ -279,10 +279,10 @@ SignerListSet::replaceSignerList() // This may be either a create or a replace. Preemptively remove any // old signer list. May reduce the reserve, so this is done before // checking the reserve. - if (TER const ter = removeSignersFromLedger(ctx_.registry, view(), account_, j_)) + if (TER const ter = removeSignersFromLedger(ctx_.registry, view(), accountID_, j_)) return ter; - WritableAccountRoot wrappedAcct(account_, view()); + WritableAccountRoot wrappedAcct(accountID_, view()); if (!wrappedAcct) return tefINTERNAL; // LCOV_EXCL_LINE @@ -301,8 +301,8 @@ SignerListSet::replaceSignerList() return tecINSUFFICIENT_RESERVE; // Everything's ducky. Add the ltSIGNER_LIST to the ledger. - Keylet const ownerDirKeylet = keylet::ownerDir(account_); - Keylet const signerListKeylet = keylet::signers(account_); + Keylet const ownerDirKeylet = keylet::ownerDir(accountID_); + Keylet const signerListKeylet = keylet::signers(accountID_); auto signerList = std::make_shared(signerListKeylet); view().insert(signerList); writeSignersToSLE(signerList, flags); @@ -310,9 +310,9 @@ SignerListSet::replaceSignerList() auto viewJ = ctx_.registry.journal("View"); // Add the signer list to the account's directory. auto const page = - ctx_.view().dirInsert(ownerDirKeylet, signerListKeylet, describeOwnerDir(account_)); + ctx_.view().dirInsert(ownerDirKeylet, signerListKeylet, describeOwnerDir(accountID_)); - JLOG(j_.trace()) << "Create signer list for account " << toBase58(account_) << ": " + JLOG(j_.trace()) << "Create signer list for account " << toBase58(accountID_) << ": " << (page ? "success" : "failure"); if (!page) @@ -331,14 +331,14 @@ SignerListSet::destroySignerList() { // Destroying the signer list is only allowed if either the master key // is enabled or there is a regular key. - WritableAccountRoot wrappedAcct(account_, view()); + WritableAccountRoot wrappedAcct(accountID_, view()); if (!wrappedAcct) return tefINTERNAL; // LCOV_EXCL_LINE if ((wrappedAcct->isFlag(lsfDisableMaster)) && (!wrappedAcct->isFieldPresent(sfRegularKey))) return tecNO_ALTERNATIVE_KEY; - return removeSignersFromLedger(ctx_.registry, view(), account_, j_); + return removeSignersFromLedger(ctx_.registry, view(), accountID_, j_); } void @@ -347,7 +347,7 @@ SignerListSet::writeSignersToSLE(SLE::pointer const& ledgerEntry, std::uint32_t // Assign the quorum, default SignerListID, and flags. if (ctx_.view().rules().enabled(fixIncludeKeyletFields)) { - ledgerEntry->setAccountID(sfOwner, account_); + ledgerEntry->setAccountID(sfOwner, accountID_); } ledgerEntry->setFieldU32(sfSignerQuorum, quorum_); ledgerEntry->setFieldU32(sfSignerListID, DEFAULT_SIGNER_LIST_ID); diff --git a/src/libxrpl/tx/transactors/bridge/XChainBridge.cpp b/src/libxrpl/tx/transactors/bridge/XChainBridge.cpp index 65abcfde30..9576b0a02f 100644 --- a/src/libxrpl/tx/transactors/bridge/XChainBridge.cpp +++ b/src/libxrpl/tx/transactors/bridge/XChainBridge.cpp @@ -103,13 +103,12 @@ checkAttestationPublicKey( AccountID const accountFromPK = calcAccountID(pk); - if (auto const sleAttestationSigningAccount = - view.read(keylet::account(attestationSignerAccount))) + if (AccountRoot const acctSigner(attestationSignerAccount, view); acctSigner) { if (accountFromPK == attestationSignerAccount) { // master key - if ((sleAttestationSigningAccount->getFieldU32(sfFlags) & lsfDisableMaster) != 0u) + if (acctSigner->getFieldU32(sfFlags) & lsfDisableMaster) { JLOG(j.trace()) << "Attempt to add an attestation with " "disabled master key."; @@ -119,8 +118,7 @@ checkAttestationPublicKey( else { // regular key - if (std::optional regularKey = - (*sleAttestationSigningAccount)[~sfRegularKey]; + if (std::optional regularKey = acctSigner->at(~sfRegularKey); regularKey != accountFromPK) { if (!regularKey) @@ -381,12 +379,12 @@ transferHelper( if (dst == src) return tesSUCCESS; - auto const dstK = keylet::account(dst); - if (auto sleDst = psb.read(dstK)) + AccountRoot const acctDst(dst, psb); + if (acctDst) { // Check dst tag and deposit auth - if (((sleDst->getFlags() & lsfRequireDestTag) != 0u) && !dstTag) + if ((acctDst->getFlags() & lsfRequireDestTag) && !dstTag) return tecDST_TAG_NEEDED; // If the destination is the claim owner, and this is a claim @@ -395,7 +393,7 @@ transferHelper( bool const canBypassDepositAuth = dst == claimOwner && depositAuthPolicy == DepositAuthPolicy::dstCanBypass; - if (!canBypassDepositAuth && ((sleDst->getFlags() & lsfDepositAuth) != 0u) && + if (!canBypassDepositAuth && (acctDst->getFlags() & lsfDepositAuth) && !psb.exists(keylet::depositPreauth(dst, src))) { return tecNO_PERMISSION; @@ -408,17 +406,17 @@ transferHelper( if (amt.native()) { - auto const sleSrc = psb.peek(keylet::account(src)); - XRPL_ASSERT(sleSrc, "xrpl::transferHelper : non-null source account"); - if (!sleSrc) + WritableAccountRoot acctSrc(src, psb); + XRPL_ASSERT(acctSrc, "xrpl::transferHelper : non-null source account"); + if (!acctSrc) return tecINTERNAL; // LCOV_EXCL_LINE { - auto const ownerCount = sleSrc->getFieldU32(sfOwnerCount); + auto const ownerCount = acctSrc->getFieldU32(sfOwnerCount); auto const reserve = psb.fees().accountReserve(ownerCount); auto const availableBalance = [&]() -> STAmount { - STAmount const curBal = (*sleSrc)[sfBalance]; + STAmount const curBal = acctSrc->at(sfBalance); // Checking that account == src and postFeeBalance == curBal is // not strictly necessary, but helps protect against future // changes @@ -434,8 +432,8 @@ transferHelper( } } - auto sleDst = psb.peek(dstK); - if (!sleDst) + WritableAccountRoot acctDst(dst, psb); + if (!acctDst) { if (canCreate == CanCreateDstPolicy::no) { @@ -449,17 +447,17 @@ transferHelper( } // Create the account. - sleDst = std::make_shared(dstK); - sleDst->setAccountID(sfAccount, dst); - sleDst->setFieldU32(sfSequence, psb.seq()); + acctDst.newSLE(); + acctDst->setAccountID(sfAccount, dst); + acctDst->setFieldU32(sfSequence, psb.seq()); - psb.insert(sleDst); + acctDst.insert(); } - (*sleSrc)[sfBalance] = (*sleSrc)[sfBalance] - amt; - (*sleDst)[sfBalance] = (*sleDst)[sfBalance] + amt; - psb.update(sleSrc); - psb.update(sleDst); + acctSrc->at(sfBalance) = acctSrc->at(sfBalance) - amt; + acctDst->at(sfBalance) = acctDst->at(sfBalance) + amt; + acctSrc.update(); + acctDst.update(); return tesSUCCESS; } @@ -730,9 +728,9 @@ getSignersListAndQuorum(ReadView const& view, SLE const& sleBridge, beast::Journ std::uint32_t q = std::numeric_limits::max(); AccountID const thisDoor = sleBridge[sfAccount]; - auto const sleDoor = [&] { return view.read(keylet::account(thisDoor)); }(); + AccountRoot const acctDoor(thisDoor, view); - if (!sleDoor) + if (!acctDoor) { return {r, q, tecINTERNAL}; } @@ -1395,25 +1393,25 @@ XChainCreateBridge::preclaim(PreclaimContext const& ctx) if (!isXRP(bridgeSpec.issue(chainType))) { - auto const sleIssuer = ctx.view.read(keylet::account(bridgeSpec.issue(chainType).account)); + AccountRoot const acctIssuer(bridgeSpec.issue(chainType).account, ctx.view); - if (!sleIssuer) + if (!acctIssuer) return tecNO_ISSUER; // Allowing clawing back funds would break the bridge's invariant that // wrapped funds are always backed by locked funds - if ((sleIssuer->getFlags() & lsfAllowTrustLineClawback) != 0u) + if (acctIssuer->getFlags() & lsfAllowTrustLineClawback) return tecNO_PERMISSION; } { // Check reserve - auto const sleAcc = ctx.view.read(keylet::account(account)); - if (!sleAcc) + AccountRoot const acctSrc(account, ctx.view); + if (!acctSrc) return terNO_ACCOUNT; - auto const balance = (*sleAcc)[sfBalance]; - auto const reserve = ctx.view.fees().accountReserve((*sleAcc)[sfOwnerCount] + 1); + auto const balance = acctSrc->at(sfBalance); + auto const reserve = ctx.view.fees().accountReserve(acctSrc->getFieldU32(sfOwnerCount) + 1); if (balance < reserve) return tecINSUFFICIENT_RESERVE; @@ -1541,8 +1539,7 @@ BridgeModify::doApply() auto const minAccountCreate = ctx_.tx[~sfMinAccountCreateAmount]; bool const clearAccountCreate = (ctx_.tx.getFlags() & tfClearAccountCreateAmount) != 0u; - auto const sleAcct = ctx_.view().peek(keylet::account(account)); - if (!sleAcct) + if (!AccountRoot(account, ctx_.view())) return tecINTERNAL; // LCOV_EXCL_LINE STXChainBridge::ChainType const chainType = @@ -1599,7 +1596,7 @@ XChainClaim::preclaim(PreclaimContext const& ctx) return tecNO_ENTRY; } - if (!ctx.view.read(keylet::account(ctx.tx[sfDestination]))) + if (!AccountRoot(ctx.tx[sfDestination], ctx.view)) { return tecNO_DST; } @@ -1704,11 +1701,11 @@ XChainClaim::doApply() // `finalizeClaimHelper`. Since `finalizeClaimHelper` can create child // views, it's important that the sle's lifetime doesn't overlap. - auto const sleAcct = psb.peek(keylet::account(account)); + AccountRoot const acctRoot(account, psb); auto const sleBridge = peekBridge(psb, bridgeSpec); auto const sleClaimID = psb.peek(claimIDKeylet); - if (!(sleBridge && sleClaimID && sleAcct)) + if (!(sleBridge && sleClaimID && acctRoot)) return Unexpected(tecINTERNAL); AccountID const thisDoor = (*sleBridge)[sfAccount]; @@ -1885,8 +1882,8 @@ XChainCommit::doApply() auto const amount = ctx_.tx[sfAmount]; auto const bridgeSpec = ctx_.tx[sfXChainBridge]; - auto const sleAccount = psb.read(keylet::account(account)); - if (!sleAccount) + AccountRoot const acctRoot(account, psb); + if (!acctRoot) return tecINTERNAL; // LCOV_EXCL_LINE auto const sleBridge = readBridge(psb, bridgeSpec); @@ -1897,7 +1894,7 @@ XChainCommit::doApply() // Support dipping into reserves to pay the fee TransferHelperSubmittingAccountInfo submittingAccountInfo{ - account_, preFeeBalance_, (*sleAccount)[sfBalance]}; + accountID_, preFeeBalance_, (*acctRoot)[sfBalance]}; auto const thTer = transferHelper( psb, @@ -1954,12 +1951,12 @@ XChainCreateClaimID::preclaim(PreclaimContext const& ctx) { // Check reserve - auto const sleAcc = ctx.view.read(keylet::account(account)); - if (!sleAcc) + AccountRoot const acctSrc(account, ctx.view); + if (!acctSrc) return terNO_ACCOUNT; - auto const balance = (*sleAcc)[sfBalance]; - auto const reserve = ctx.view.fees().accountReserve((*sleAcc)[sfOwnerCount] + 1); + auto const balance = acctSrc->at(sfBalance); + auto const reserve = ctx.view.fees().accountReserve(acctSrc->getFieldU32(sfOwnerCount) + 1); if (balance < reserve) return tecINSUFFICIENT_RESERVE; @@ -2159,8 +2156,8 @@ XChainCreateAccountCommit::doApply() STAmount const reward = ctx_.tx[sfSignatureReward]; STXChainBridge const bridge = ctx_.tx[sfXChainBridge]; - auto const sle = psb.peek(keylet::account(account)); - if (!sle) + AccountRoot const acctRoot(account, psb); + if (!acctRoot) return tecINTERNAL; // LCOV_EXCL_LINE auto const sleBridge = peekBridge(psb, bridge); @@ -2171,7 +2168,7 @@ XChainCreateAccountCommit::doApply() // Support dipping into reserves to pay the fee TransferHelperSubmittingAccountInfo submittingAccountInfo{ - account_, preFeeBalance_, (*sle)[sfBalance]}; + accountID_, preFeeBalance_, (*acctRoot)[sfBalance]}; STAmount const toTransfer = amount + reward; auto const thTer = transferHelper( psb, diff --git a/src/libxrpl/tx/transactors/check/CheckCash.cpp b/src/libxrpl/tx/transactors/check/CheckCash.cpp index 1fe441c698..09a7b76462 100644 --- a/src/libxrpl/tx/transactors/check/CheckCash.cpp +++ b/src/libxrpl/tx/transactors/check/CheckCash.cpp @@ -73,16 +73,16 @@ CheckCash::preclaim(PreclaimContext const& ctx) // LCOV_EXCL_STOP } { - auto const sleSrc = ctx.view.read(keylet::account(srcId)); - auto const sleDst = ctx.view.read(keylet::account(dstId)); - if (!sleSrc || !sleDst) + AccountRoot const acctSrc(srcId, ctx.view); + AccountRoot const acctDst(dstId, ctx.view); + if (!acctSrc || !acctDst) { // If the check exists this should never occur. JLOG(ctx.j.warn()) << "Malformed transaction: source or destination not in ledger"; return tecNO_ENTRY; } - if (((sleDst->getFlags() & lsfRequireDestTag) != 0u) && + if ((acctDst->getFlags() & lsfRequireDestTag) && !sleCheck->isFieldPresent(sfDestinationTag)) { // The tag is basically account-specific information we don't @@ -148,15 +148,15 @@ CheckCash::preclaim(PreclaimContext const& ctx) // An issuer can always accept their own currency. if (!value.native() && (value.getIssuer() != dstId)) { - auto const sleIssuer = ctx.view.read(keylet::account(issuerId)); - if (!sleIssuer) + AccountRoot const acctIssuer(issuerId, ctx.view); + if (!acctIssuer) { JLOG(ctx.j.warn()) << "Can't receive IOUs from non-existent issuer: " << to_string(issuerId); return tecNO_ISSUER; } - if ((sleIssuer->at(sfFlags) & lsfRequireAuth) != 0u) + if (acctIssuer->at(sfFlags) & lsfRequireAuth) { auto const sleTrustLine = ctx.view.read(keylet::line(dstId, issuerId, currency)); @@ -215,7 +215,7 @@ CheckCash::doApply() } AccountID const srcId{sleCheck->getAccountID(sfAccount)}; - if (!psb.exists(keylet::account(srcId)) || !psb.exists(keylet::account(account_))) + if (!psb.exists(keylet::account(srcId)) || !psb.exists(keylet::account(accountID_))) { // LCOV_EXCL_START JLOG(ctx_.journal.fatal()) << "Precheck did not verify source or destination's existence."; @@ -236,7 +236,7 @@ CheckCash::doApply() auto viewJ = ctx_.registry.journal("View"); auto const optDeliverMin = ctx_.tx[~sfDeliverMin]; - if (srcId != account_) + if (srcId != accountID_) { STAmount const sendMax = sleCheck->at(sfSendMax); @@ -275,7 +275,7 @@ CheckCash::doApply() } // The source account has enough XRP so make the ledger change. - if (TER const ter{transferXRP(psb, srcId, account_, xrpDeliver, viewJ)}; + if (TER const ter{transferXRP(psb, srcId, accountID_, xrpDeliver, viewJ)}; !isTesSuccess(ter)) { // The transfer failed. Return the error code. @@ -298,9 +298,9 @@ CheckCash::doApply() // If a trust line does not exist yet create one. Issue const& trustLineIssue = flowDeliver.issue(); AccountID const issuer = flowDeliver.getIssuer(); - AccountID const truster = issuer == account_ ? srcId : account_; + AccountID const truster = issuer == accountID_ ? srcId : accountID_; Keylet const trustLineKey = keylet::line(truster, trustLineIssue); - bool const destLow = issuer > account_; + bool const destLow = issuer > accountID_; if (!psb.exists(trustLineKey)) { @@ -311,7 +311,7 @@ CheckCash::doApply() // a. this (destination) account and // b. issuing account (not sending account). - WritableAccountRoot wrappedDst(account_, psb); + WritableAccountRoot wrappedDst(accountID_, psb); // Can the account cover the trust line's reserve? if (std::uint32_t const ownerCount = {wrappedDst->at(sfOwnerCount)}; @@ -332,7 +332,7 @@ CheckCash::doApply() psb, // payment sandbox destLow, // is dest low? issuer, // source - account_, // destination + accountID_, // destination trustLineKey.key, // ledger index wrappedDst, // Account to add to false, // authorize account @@ -340,7 +340,7 @@ CheckCash::doApply() false, // freeze trust line false, // deep freeze trust line initialBalance, // zero initial balance - Issue(currency, account_), // limit of zero + Issue(currency, accountID_), // limit of zero 0, // quality in 0, // quality out viewJ); // journal @@ -384,7 +384,7 @@ CheckCash::doApply() psb, flowDeliver, srcId, - account_, + accountID_, STPathSet{}, true, // default path static_cast(optDeliverMin), // partial payment @@ -421,9 +421,9 @@ CheckCash::doApply() // Check was cashed. If not a self send (and it shouldn't be), remove // check link from destination directory. - if (srcId != account_ && + if (srcId != accountID_ && !psb.dirRemove( - keylet::ownerDir(account_), sleCheck->at(sfDestinationNode), sleCheck->key(), true)) + keylet::ownerDir(accountID_), sleCheck->at(sfDestinationNode), sleCheck->key(), true)) { // LCOV_EXCL_START JLOG(j_.fatal()) << "Unable to delete check from destination."; diff --git a/src/libxrpl/tx/transactors/check/CheckCreate.cpp b/src/libxrpl/tx/transactors/check/CheckCreate.cpp index 532bc7c15c..3363f3fc9e 100644 --- a/src/libxrpl/tx/transactors/check/CheckCreate.cpp +++ b/src/libxrpl/tx/transactors/check/CheckCreate.cpp @@ -53,14 +53,14 @@ TER CheckCreate::preclaim(PreclaimContext const& ctx) { AccountID const dstId{ctx.tx[sfDestination]}; - auto const sleDst = ctx.view.read(keylet::account(dstId)); - if (!sleDst) + AccountRoot const acctDst(dstId, ctx.view); + if (!acctDst) { JLOG(ctx.j.warn()) << "Destination account does not exist."; return tecNO_DST; } - auto const flags = sleDst->getFlags(); + auto const flags = acctDst->getFlags(); // Check if the destination has disallowed incoming checks if ((flags & lsfDisallowIncomingCheck) != 0u) @@ -70,7 +70,7 @@ CheckCreate::preclaim(PreclaimContext const& ctx) // because all writes to pseudo-account discriminator fields **are** // amendment gated, hence the behaviour of this check will always match the // currently active amendments. - if (isPseudoAccount(sleDst)) + if (acctDst.isPseudoAccount()) return tecNO_PERMISSION; if (((flags & lsfRequireDestTag) != 0u) && !ctx.tx.isFieldPresent(sfDestinationTag)) @@ -134,7 +134,7 @@ CheckCreate::preclaim(PreclaimContext const& ctx) TER CheckCreate::doApply() { - WritableAccountRoot wrappedAcct(account_, view()); + WritableAccountRoot wrappedAcct(accountID_, view()); if (!wrappedAcct) return tefINTERNAL; // LCOV_EXCL_LINE @@ -152,10 +152,10 @@ CheckCreate::doApply() // Note that we use the value from the sequence or ticket as the // Check sequence. For more explanation see comments in SeqProxy.h. std::uint32_t const seq = ctx_.tx.getSeqValue(); - Keylet const checkKeylet = keylet::check(account_, seq); + Keylet const checkKeylet = keylet::check(accountID_, seq); auto sleCheck = std::make_shared(checkKeylet); - sleCheck->setAccountID(sfAccount, account_); + sleCheck->setAccountID(sfAccount, accountID_); AccountID const dstAccountId = ctx_.tx[sfDestination]; sleCheck->setAccountID(sfDestination, dstAccountId); sleCheck->setFieldU32(sfSequence, seq); @@ -174,7 +174,7 @@ CheckCreate::doApply() auto viewJ = ctx_.registry.journal("View"); // If it's not a self-send (and it shouldn't be), add Check to the // destination's owner directory. - if (dstAccountId != account_) + if (dstAccountId != accountID_) { auto const page = view().dirInsert( keylet::ownerDir(dstAccountId), checkKeylet, describeOwnerDir(dstAccountId)); @@ -189,8 +189,8 @@ CheckCreate::doApply() } { - auto const page = - view().dirInsert(keylet::ownerDir(account_), checkKeylet, describeOwnerDir(account_)); + auto const page = view().dirInsert( + keylet::ownerDir(accountID_), checkKeylet, describeOwnerDir(accountID_)); JLOG(j_.trace()) << "Adding Check to owner directory " << to_string(checkKeylet.key) << ": " << (page ? "success" : "failure"); diff --git a/src/libxrpl/tx/transactors/credentials/CredentialAccept.cpp b/src/libxrpl/tx/transactors/credentials/CredentialAccept.cpp index 06eb44c2fd..728e501cf2 100644 --- a/src/libxrpl/tx/transactors/credentials/CredentialAccept.cpp +++ b/src/libxrpl/tx/transactors/credentials/CredentialAccept.cpp @@ -76,7 +76,7 @@ CredentialAccept::doApply() AccountID const issuer{ctx_.tx[sfIssuer]}; // Both exist as credential object exist itself (checked in preclaim) - WritableAccountRoot wrappedSubject(account_, view()); + WritableAccountRoot wrappedSubject(accountID_, view()); WritableAccountRoot wrappedIssuer(issuer, view()); if (!wrappedSubject || !wrappedIssuer) @@ -90,7 +90,7 @@ CredentialAccept::doApply() } auto const credType(ctx_.tx[sfCredentialType]); - Keylet const credentialKey = keylet::credential(account_, issuer, credType); + Keylet const credentialKey = keylet::credential(accountID_, issuer, credType); auto const sleCred = view().peek(credentialKey); // Checked in preclaim() if (checkExpired(sleCred, view().header().parentCloseTime)) diff --git a/src/libxrpl/tx/transactors/credentials/CredentialCreate.cpp b/src/libxrpl/tx/transactors/credentials/CredentialCreate.cpp index 3ade745b29..eb33ab569e 100644 --- a/src/libxrpl/tx/transactors/credentials/CredentialCreate.cpp +++ b/src/libxrpl/tx/transactors/credentials/CredentialCreate.cpp @@ -89,7 +89,7 @@ CredentialCreate::doApply() { auto const subject = ctx_.tx[sfSubject]; auto const credType(ctx_.tx[sfCredentialType]); - Keylet const credentialKey = keylet::credential(subject, account_, credType); + Keylet const credentialKey = keylet::credential(subject, accountID_, credType); auto const sleCred = std::make_shared(credentialKey); if (!sleCred) @@ -111,7 +111,7 @@ CredentialCreate::doApply() sleCred->setFieldU32(sfExpiration, *optExp); } - WritableAccountRoot wrappedIssuer(account_, view()); + WritableAccountRoot wrappedIssuer(accountID_, view()); if (!wrappedIssuer) return tefINTERNAL; // LCOV_EXCL_LINE @@ -123,15 +123,15 @@ CredentialCreate::doApply() } sleCred->setAccountID(sfSubject, subject); - sleCred->setAccountID(sfIssuer, account_); + sleCred->setAccountID(sfIssuer, accountID_); sleCred->setFieldVL(sfCredentialType, credType); if (ctx_.tx.isFieldPresent(sfURI)) sleCred->setFieldVL(sfURI, ctx_.tx.getFieldVL(sfURI)); { - auto const page = - view().dirInsert(keylet::ownerDir(account_), credentialKey, describeOwnerDir(account_)); + auto const page = view().dirInsert( + keylet::ownerDir(accountID_), credentialKey, describeOwnerDir(accountID_)); JLOG(j_.trace()) << "Adding Credential to owner directory " << to_string(credentialKey.key) << ": " << (page ? "success" : "failure"); if (!page) @@ -141,7 +141,7 @@ CredentialCreate::doApply() wrappedIssuer.adjustOwnerCount(1, j_); } - if (subject == account_) + if (subject == accountID_) { sleCred->setFieldU32(sfFlags, lsfAccepted); } diff --git a/src/libxrpl/tx/transactors/credentials/CredentialDelete.cpp b/src/libxrpl/tx/transactors/credentials/CredentialDelete.cpp index 5f78ba6757..a9fedb2416 100644 --- a/src/libxrpl/tx/transactors/credentials/CredentialDelete.cpp +++ b/src/libxrpl/tx/transactors/credentials/CredentialDelete.cpp @@ -69,15 +69,15 @@ CredentialDelete::preclaim(PreclaimContext const& ctx) TER CredentialDelete::doApply() { - auto const subject = ctx_.tx[~sfSubject].value_or(account_); - auto const issuer = ctx_.tx[~sfIssuer].value_or(account_); + auto const subject = ctx_.tx[~sfSubject].value_or(accountID_); + auto const issuer = ctx_.tx[~sfIssuer].value_or(accountID_); auto const credType(ctx_.tx[sfCredentialType]); auto const sleCred = view().peek(keylet::credential(subject, issuer, credType)); if (!sleCred) return tefINTERNAL; // LCOV_EXCL_LINE - if ((subject != account_) && (issuer != account_) && + if ((subject != accountID_) && (issuer != accountID_) && !checkExpired(sleCred, ctx_.view().header().parentCloseTime)) { JLOG(j_.trace()) << "Can't delete non-expired credential."; diff --git a/src/libxrpl/tx/transactors/delegate/DelegateSet.cpp b/src/libxrpl/tx/transactors/delegate/DelegateSet.cpp index 327d34590c..304a9caf42 100644 --- a/src/libxrpl/tx/transactors/delegate/DelegateSet.cpp +++ b/src/libxrpl/tx/transactors/delegate/DelegateSet.cpp @@ -56,12 +56,12 @@ DelegateSet::preclaim(PreclaimContext const& ctx) TER DelegateSet::doApply() { - WritableAccountRoot wrappedOwner(account_, ctx_.view()); + WritableAccountRoot wrappedOwner(accountID_, ctx_.view()); if (!wrappedOwner) return tefINTERNAL; // LCOV_EXCL_LINE auto const& authAccount = ctx_.tx[sfAuthorize]; - auto const delegateKey = keylet::delegate(account_, authAccount); + auto const delegateKey = keylet::delegate(accountID_, authAccount); auto sle = ctx_.view().peek(delegateKey); if (sle) @@ -70,7 +70,7 @@ DelegateSet::doApply() if (permissions.empty()) { // if permissions array is empty, delete the ledger object. - return deleteDelegate(view(), sle, account_, j_); + return deleteDelegate(view(), sle, accountID_, j_); } sle->setFieldArray(sfPermissions, permissions); @@ -89,12 +89,12 @@ DelegateSet::doApply() return tecINSUFFICIENT_RESERVE; sle = std::make_shared(delegateKey); - sle->setAccountID(sfAccount, account_); + sle->setAccountID(sfAccount, accountID_); sle->setAccountID(sfAuthorize, authAccount); sle->setFieldArray(sfPermissions, permissions); auto const page = - ctx_.view().dirInsert(keylet::ownerDir(account_), delegateKey, describeOwnerDir(account_)); + ctx_.view().dirInsert(keylet::ownerDir(accountID_), delegateKey, describeOwnerDir(accountID_)); if (!page) return tecDIR_FULL; // LCOV_EXCL_LINE diff --git a/src/libxrpl/tx/transactors/dex/AMMBid.cpp b/src/libxrpl/tx/transactors/dex/AMMBid.cpp index a1ace702dc..fe6ce0c6e1 100644 --- a/src/libxrpl/tx/transactors/dex/AMMBid.cpp +++ b/src/libxrpl/tx/transactors/dex/AMMBid.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -90,7 +91,7 @@ AMMBid::preclaim(PreclaimContext const& ctx) { for (auto const& account : ctx.tx.getFieldArray(sfAuthAccounts)) { - if (!ctx.view.read(keylet::account(account[sfAccount]))) + if (AccountRoot const acct(account[sfAccount], ctx.view); !acct) { JLOG(ctx.j.debug()) << "AMM Bid: Invalid Account."; return terNO_ACCOUNT; @@ -147,14 +148,14 @@ AMMBid::preclaim(PreclaimContext const& ctx) } static std::pair -applyBid(ApplyContext& ctx_, Sandbox& sb, AccountID const& account_, beast::Journal j_) +applyBid(ApplyContext& ctx_, Sandbox& sb, AccountID const& accountID_, beast::Journal j_) { using namespace std::chrono; auto const ammSle = sb.peek(keylet::amm(ctx_.tx[sfAsset], ctx_.tx[sfAsset2])); if (!ammSle) return {tecINTERNAL, false}; STAmount const lptAMMBalance = (*ammSle)[sfLPTokenBalance]; - auto const lpTokens = ammLPHolds(sb, *ammSle, account_, ctx_.journal); + auto const lpTokens = ammLPHolds(sb, *ammSle, accountID_, ctx_.journal); auto const& rules = ctx_.view().rules(); if (!rules.enabled(fixInnerObjTemplate)) { @@ -186,11 +187,11 @@ applyBid(ApplyContext& ctx_, Sandbox& sb, AccountID const& account_, beast::Jour auto validOwner = [&](AccountID const& account) { // Valid range is 0-19 but the tailing slot pays MinSlotPrice // and doesn't refund so the check is < instead of <= to optimize. - return timeSlot && *timeSlot < tailingSlot && sb.read(keylet::account(account)); + return timeSlot && *timeSlot < tailingSlot && AccountRoot(account, sb); }; auto updateSlot = [&](std::uint32_t fee, Number const& minPrice, Number const& burn) -> TER { - auctionSlot.setAccountID(sfAccount, account_); + auctionSlot.setAccountID(sfAccount, accountID_); auctionSlot.setFieldU32(sfExpiration, current + TOTAL_TIME_SLOT_SECS); if (fee != 0) { @@ -221,7 +222,7 @@ applyBid(ApplyContext& ctx_, Sandbox& sb, AccountID const& account_, beast::Jour return tecINTERNAL; // LCOV_EXCL_STOP } - auto res = redeemIOU(sb, account_, saBurn, lpTokens.issue(), ctx_.journal); + auto res = redeemIOU(sb, accountID_, saBurn, lpTokens.issue(), ctx_.journal); if (!isTesSuccess(res)) { JLOG(ctx_.journal.debug()) << "AMM Bid: failed to redeem."; @@ -319,7 +320,7 @@ applyBid(ApplyContext& ctx_, Sandbox& sb, AccountID const& account_, beast::Jour } res = accountSend( sb, - account_, + accountID_, auctionSlot[sfAccount], toSTAmount(lpTokens.issue(), refund), ctx_.journal); @@ -343,7 +344,7 @@ AMMBid::doApply() // as we go on processing transactions. Sandbox sb(&ctx_.view()); - auto const result = applyBid(ctx_, sb, account_, j_); + auto const result = applyBid(ctx_, sb, accountID_, j_); if (result.second) sb.apply(ctx_.rawView()); diff --git a/src/libxrpl/tx/transactors/dex/AMMClawback.cpp b/src/libxrpl/tx/transactors/dex/AMMClawback.cpp index b8f4fe4b1b..9fe7620c91 100644 --- a/src/libxrpl/tx/transactors/dex/AMMClawback.cpp +++ b/src/libxrpl/tx/transactors/dex/AMMClawback.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -72,11 +73,11 @@ AMMClawback::preclaim(PreclaimContext const& ctx) { auto const asset = ctx.tx[sfAsset].get(); auto const asset2 = ctx.tx[sfAsset2].get(); - auto const sleIssuer = ctx.view.read(keylet::account(ctx.tx[sfAccount])); - if (!sleIssuer) + AccountRoot const acctIssuer(ctx.tx[sfAccount], ctx.view); + if (!acctIssuer) return terNO_ACCOUNT; // LCOV_EXCL_LINE - if (!ctx.view.read(keylet::account(ctx.tx[sfHolder]))) + if (AccountRoot const acctHolder(ctx.tx[sfHolder], ctx.view); !acctHolder) return terNO_ACCOUNT; auto const ammSle = ctx.view.read(keylet::amm(asset, asset2)); @@ -86,7 +87,7 @@ AMMClawback::preclaim(PreclaimContext const& ctx) return terNO_AMM; } - std::uint32_t const issuerFlagsIn = sleIssuer->getFieldU32(sfFlags); + std::uint32_t const issuerFlagsIn = acctIssuer->getFieldU32(sfFlags); // If AllowTrustLineClawback is not set or NoFreeze is set, return no // permission @@ -123,8 +124,8 @@ AMMClawback::applyGuts(Sandbox& sb) return tecINTERNAL; // LCOV_EXCL_LINE auto const ammAccount = (*ammSle)[sfAccount]; - auto const accountSle = sb.read(keylet::account(ammAccount)); - if (!accountSle) + AccountRoot const ammAcct(ammAccount, sb); + if (!ammAcct) return tecINTERNAL; // LCOV_EXCL_LINE if (sb.rules().enabled(fixAMMClawbackRounding)) diff --git a/src/libxrpl/tx/transactors/dex/AMMCreate.cpp b/src/libxrpl/tx/transactors/dex/AMMCreate.cpp index 13495f5da7..8c0b6b6115 100644 --- a/src/libxrpl/tx/transactors/dex/AMMCreate.cpp +++ b/src/libxrpl/tx/transactors/dex/AMMCreate.cpp @@ -97,8 +97,9 @@ AMMCreate::preclaim(PreclaimContext const& ctx) if (isXRP(issue)) return false; - if (auto const issuerAccount = view.read(keylet::account(issue.account))) - return (issuerAccount->getFlags() & lsfDefaultRipple) == 0; + AccountRoot const issuerAcct(issue.account, view); + if (issuerAcct) + return (issuerAcct->getFlags() & lsfDefaultRipple) == 0; return false; }; @@ -135,8 +136,9 @@ AMMCreate::preclaim(PreclaimContext const& ctx) } auto isLPToken = [&](STAmount const& amount) -> bool { - if (auto const sle = ctx.view.read(keylet::account(amount.issue().account))) - return sle->isFieldPresent(sfAMMID); + AccountRoot const acct(amount.issue().account, ctx.view); + if (acct) + return acct->isFieldPresent(sfAMMID); return false; }; @@ -165,10 +167,10 @@ AMMCreate::preclaim(PreclaimContext const& ctx) auto clawbackDisabled = [&](Issue const& issue) -> TER { if (isXRP(issue)) return tesSUCCESS; - auto const sle = ctx.view.read(keylet::account(issue.account)); - if (!sle) + AccountRoot const acct(issue.account, ctx.view); + if (!acct) return tecINTERNAL; // LCOV_EXCL_LINE - if (sle->getFlags() & lsfAllowTrustLineClawback) + if (acct->getFlags() & lsfAllowTrustLineClawback) return tecNO_PERMISSION; return tesSUCCESS; }; @@ -179,7 +181,7 @@ AMMCreate::preclaim(PreclaimContext const& ctx) } static std::pair -applyCreate(ApplyContext& ctx_, Sandbox& sb, AccountID const& account_, beast::Journal j_) +applyCreate(ApplyContext& ctx_, Sandbox& sb, AccountID const& accountID_, beast::Journal j_) { auto const amount = ctx_.tx[sfAmount]; auto const amount2 = ctx_.tx[sfAmount2]; @@ -222,7 +224,7 @@ applyCreate(ApplyContext& ctx_, Sandbox& sb, AccountID const& account_, beast::J ammSle->setFieldIssue(sfAsset, STIssue{sfAsset, issue1}); ammSle->setFieldIssue(sfAsset2, STIssue{sfAsset2, issue2}); // AMM creator gets the auction slot and the voting slot. - initializeFeeAuctionVote(ctx_.view(), ammSle, account_, lptIss, ctx_.tx[sfTradingFee]); + initializeFeeAuctionVote(ctx_.view(), ammSle, accountID_, lptIss, ctx_.tx[sfTradingFee]); // Add owner directory to link the root account and AMM object. if (auto ter = dirLink(sb, accountId, ammSle); ter) @@ -233,7 +235,7 @@ applyCreate(ApplyContext& ctx_, Sandbox& sb, AccountID const& account_, beast::J sb.insert(ammSle); // Send LPT to LP. - auto res = accountSend(sb, accountId, account_, lpTokens, ctx_.journal); + auto res = accountSend(sb, accountId, accountID_, lpTokens, ctx_.journal); if (!isTesSuccess(res)) { JLOG(j_.debug()) << "AMM Instance: failed to send LPT " << lpTokens; @@ -242,7 +244,7 @@ applyCreate(ApplyContext& ctx_, Sandbox& sb, AccountID const& account_, beast::J auto sendAndTrustSet = [&](STAmount const& amount) -> TER { if (auto const res = - accountSend(sb, account_, accountId, amount, ctx_.journal, WaiveTransferFee::Yes)) + accountSend(sb, accountID_, accountId, amount, ctx_.journal, WaiveTransferFee::Yes)) return res; // Set AMM flag on AMM trustline if (!isXRP(amount)) @@ -297,7 +299,7 @@ AMMCreate::doApply() // as we go on processing transactions. Sandbox sb(&ctx_.view()); - auto const result = applyCreate(ctx_, sb, account_, j_); + auto const result = applyCreate(ctx_, sb, accountID_, j_); if (result.second) sb.apply(ctx_.rawView()); diff --git a/src/libxrpl/tx/transactors/dex/AMMDeposit.cpp b/src/libxrpl/tx/transactors/dex/AMMDeposit.cpp index 085f8700e9..76995eb1db 100644 --- a/src/libxrpl/tx/transactors/dex/AMMDeposit.cpp +++ b/src/libxrpl/tx/transactors/dex/AMMDeposit.cpp @@ -348,7 +348,7 @@ AMMDeposit::applyGuts(Sandbox& sb) auto const [amountBalance, amount2Balance, lptAMMBalance] = *expected; auto const tfee = (lptAMMBalance == beast::zero) ? ctx_.tx[~sfTradingFee].value_or(0) - : getTradingFee(ctx_.view(), *ammSle, account_); + : getTradingFee(ctx_.view(), *ammSle, accountID_); auto const subTxType = ctx_.tx.getFlags() & tfDepositSubTx; @@ -419,7 +419,7 @@ AMMDeposit::applyGuts(Sandbox& sb) // LP depositing into AMM empty state gets the auction slot // and the voting if (lptAMMBalance == beast::zero) - initializeFeeAuctionVote(sb, ammSle, account_, lptAMMBalance.issue(), tfee); + initializeFeeAuctionVote(sb, ammSle, accountID_, lptAMMBalance.issue(), tfee); sb.update(ammSle); } @@ -457,7 +457,7 @@ AMMDeposit::deposit( { // Check account has sufficient funds. // Return true if it does, false otherwise. - WritableAccountRoot wrappedAcct(account_, view); + WritableAccountRoot wrappedAcct(accountID_, view); auto checkBalance = [&](auto const& depositAmount) -> TER { if (depositAmount <= beast::zero) return temBAD_AMOUNT; @@ -465,15 +465,15 @@ AMMDeposit::deposit( { auto const& lpIssue = lpTokensDeposit.issue(); // Adjust the reserve if LP doesn't have LPToken trustline - auto const sle = view.read(keylet::line(account_, lpIssue.account, lpIssue.currency)); + auto const sle = view.read(keylet::line(accountID_, lpIssue.account, lpIssue.currency)); if (wrappedAcct.xrpLiquid(!sle, j_) >= depositAmount) return tesSUCCESS; } else if ( - account_ == depositAmount.issue().account || + accountID_ == depositAmount.issue().account || accountHolds( view, - account_, + accountID_, depositAmount.issue(), FreezeHandling::fhIGNORE_FREEZE, ctx_.journal) >= depositAmount) @@ -520,7 +520,7 @@ AMMDeposit::deposit( } auto res = accountSend( - view, account_, ammAccount, amountDepositActual, ctx_.journal, WaiveTransferFee::Yes); + view, accountID_, ammAccount, amountDepositActual, ctx_.journal, WaiveTransferFee::Yes); if (!isTesSuccess(res)) { JLOG(ctx_.journal.debug()) << "AMM Deposit: failed to deposit " << amountDepositActual; @@ -539,7 +539,7 @@ AMMDeposit::deposit( } res = accountSend( - view, account_, ammAccount, *amount2DepositActual, ctx_.journal, WaiveTransferFee::Yes); + view, accountID_, ammAccount, *amount2DepositActual, ctx_.journal, WaiveTransferFee::Yes); if (!isTesSuccess(res)) { JLOG(ctx_.journal.debug()) @@ -549,7 +549,7 @@ AMMDeposit::deposit( } // Deposit LP tokens - res = accountSend(view, ammAccount, account_, lpTokensDepositActual, ctx_.journal); + res = accountSend(view, ammAccount, accountID_, lpTokensDepositActual, ctx_.journal); if (!isTesSuccess(res)) { JLOG(ctx_.journal.debug()) << "AMM Deposit: failed to deposit LPTokens"; diff --git a/src/libxrpl/tx/transactors/dex/AMMUtils.cpp b/src/libxrpl/tx/transactors/dex/AMMUtils.cpp index 91891ce86f..3b0579f58c 100644 --- a/src/libxrpl/tx/transactors/dex/AMMUtils.cpp +++ b/src/libxrpl/tx/transactors/dex/AMMUtils.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -184,8 +185,8 @@ ammAccountHolds(ReadView const& view, AccountID const& ammAccountID, Issue const { if (isXRP(issue)) { - if (auto const sle = view.read(keylet::account(ammAccountID))) - return (*sle)[sfBalance]; + if (AccountRoot const acct(ammAccountID, view); acct) + return (*acct)[sfBalance]; } else if ( auto const sle = view.read(keylet::line(ammAccountID, issue.account, issue.currency)); @@ -255,8 +256,8 @@ deleteAMMAccount(Sandbox& sb, Issue const& asset, Issue const& asset2, beast::Jo } auto const ammAccountID = (*ammSle)[sfAccount]; - auto sleAMMRoot = sb.peek(keylet::account(ammAccountID)); - if (!sleAMMRoot) + WritableAccountRoot ammRoot(ammAccountID, sb); + if (!ammRoot) { // LCOV_EXCL_START JLOG(j.error()) << "deleteAMMAccount: AMM account does not exist " @@ -287,7 +288,7 @@ deleteAMMAccount(Sandbox& sb, Issue const& asset, Issue const& asset2, beast::Jo } sb.erase(ammSle); - sb.erase(sleAMMRoot); + ammRoot.erase(); return tesSUCCESS; } diff --git a/src/libxrpl/tx/transactors/dex/AMMVote.cpp b/src/libxrpl/tx/transactors/dex/AMMVote.cpp index 2096eca0f0..73e0830b1a 100644 --- a/src/libxrpl/tx/transactors/dex/AMMVote.cpp +++ b/src/libxrpl/tx/transactors/dex/AMMVote.cpp @@ -56,14 +56,14 @@ AMMVote::preclaim(PreclaimContext const& ctx) } static std::pair -applyVote(ApplyContext& ctx_, Sandbox& sb, AccountID const& account_, beast::Journal j_) +applyVote(ApplyContext& ctx_, Sandbox& sb, AccountID const& accountID_, beast::Journal j_) { auto const feeNew = ctx_.tx[sfTradingFee]; auto ammSle = sb.peek(keylet::amm(ctx_.tx[sfAsset], ctx_.tx[sfAsset2])); if (!ammSle) return {tecINTERNAL, false}; STAmount const lptAMMBalance = (*ammSle)[sfLPTokenBalance]; - auto const lpTokensNew = ammLPHolds(sb, *ammSle, account_, ctx_.journal); + auto const lpTokensNew = ammLPHolds(sb, *ammSle, accountID_, ctx_.journal); std::optional minTokens; std::size_t minPos{0}; AccountID minAccount{0}; @@ -90,7 +90,7 @@ applyVote(ApplyContext& ctx_, Sandbox& sb, AccountID const& account_, beast::Jou auto feeVal = entry[sfTradingFee]; STObject newEntry = STObject::makeInnerObject(sfVoteEntry); // The account already has the vote entry. - if (account == account_) + if (account == accountID_) { lpTokens = lpTokensNew; feeVal = feeNew; @@ -132,7 +132,7 @@ applyVote(ApplyContext& ctx_, Sandbox& sb, AccountID const& account_, beast::Jou sfVoteWeight, static_cast( Number(lpTokensNew) * VOTE_WEIGHT_SCALE_FACTOR / lptAMMBalance)); - newEntry.setAccountID(sfAccount, account_); + newEntry.setAccountID(sfAccount, accountID_); num += feeNew * lpTokensNew; den += lpTokensNew; if (minPos) @@ -214,7 +214,7 @@ AMMVote::doApply() // as we go on processing transactions. Sandbox sb(&ctx_.view()); - auto const result = applyVote(ctx_, sb, account_, j_); + auto const result = applyVote(ctx_, sb, accountID_, j_); if (result.second) sb.apply(ctx_.rawView()); diff --git a/src/libxrpl/tx/transactors/dex/AMMWithdraw.cpp b/src/libxrpl/tx/transactors/dex/AMMWithdraw.cpp index 7c87d53ea0..3d52a52393 100644 --- a/src/libxrpl/tx/transactors/dex/AMMWithdraw.cpp +++ b/src/libxrpl/tx/transactors/dex/AMMWithdraw.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -269,8 +270,8 @@ AMMWithdraw::applyGuts(Sandbox& sb) if (!ammSle) return {tecINTERNAL, false}; // LCOV_EXCL_LINE auto const ammAccountID = (*ammSle)[sfAccount]; - auto const accountSle = sb.read(keylet::account(ammAccountID)); - if (!accountSle) + AccountRoot const ammAcct(ammAccountID, sb); + if (!ammAcct) return {tecINTERNAL, false}; // LCOV_EXCL_LINE auto const lpTokens = ammLPHolds(ctx_.view(), *ammSle, ctx_.tx[sfAccount], ctx_.journal); auto const lpTokensWithdraw = @@ -280,11 +281,11 @@ AMMWithdraw::applyGuts(Sandbox& sb) // might not match the LP's trustline balance if (sb.rules().enabled(fixAMMv1_1)) { - if (auto const res = verifyAndAdjustLPTokenBalance(sb, lpTokens, ammSle, account_); !res) + if (auto const res = verifyAndAdjustLPTokenBalance(sb, lpTokens, ammSle, accountID_); !res) return {res.error(), false}; } - auto const tfee = getTradingFee(ctx_.view(), *ammSle, account_); + auto const tfee = getTradingFee(ctx_.view(), *ammSle, accountID_); auto const expected = ammHolds( sb, @@ -413,7 +414,7 @@ AMMWithdraw::withdraw( view, ammSle, ammAccount, - account_, + accountID_, amountBalance, amountWithdraw, amount2Withdraw, @@ -532,11 +533,11 @@ AMMWithdraw::withdraw( return tesSUCCESS; if (!view.exists(keylet::line(account, issue))) { - auto const sleAccount = view.read(keylet::account(account)); - if (!sleAccount) + AccountRoot const acct(account, view); + if (!acct) return tecINTERNAL; // LCOV_EXCL_LINE - auto const balance = (*sleAccount)[sfBalance].xrp(); - std::uint32_t const ownerCount = sleAccount->at(sfOwnerCount); + auto const balance = acct->getFieldAmount(sfBalance).xrp(); + std::uint32_t const ownerCount = acct->at(sfOwnerCount); // See also TrustSet::doApply() XRPAmount const reserve( @@ -628,7 +629,7 @@ AMMWithdraw::equalWithdrawTokens( std::tie(ter, newLPTokenBalance, std::ignore, std::ignore) = equalWithdrawTokens( view, ammSle, - account_, + accountID_, ammAccount, amountBalance, amount2Balance, diff --git a/src/libxrpl/tx/transactors/dex/OfferCancel.cpp b/src/libxrpl/tx/transactors/dex/OfferCancel.cpp index a9e7cac85a..55128f1159 100644 --- a/src/libxrpl/tx/transactors/dex/OfferCancel.cpp +++ b/src/libxrpl/tx/transactors/dex/OfferCancel.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -26,11 +27,11 @@ OfferCancel::preclaim(PreclaimContext const& ctx) auto const id = ctx.tx[sfAccount]; auto const offerSequence = ctx.tx[sfOfferSequence]; - auto const sle = ctx.view.read(keylet::account(id)); - if (!sle) + AccountRoot const acct(id, ctx.view); + if (!acct) return terNO_ACCOUNT; - if ((*sle)[sfSequence] <= offerSequence) + if (acct->getFieldU32(sfSequence) <= offerSequence) { JLOG(ctx.j.trace()) << "Malformed transaction: " << "Sequence " << offerSequence << " is invalid."; @@ -47,11 +48,10 @@ OfferCancel::doApply() { auto const offerSequence = ctx_.tx[sfOfferSequence]; - auto const sle = view().read(keylet::account(account_)); - if (!sle) + if (AccountRoot const acct(accountID_, view()); !acct) return tefINTERNAL; // LCOV_EXCL_LINE - if (auto sleOffer = view().peek(keylet::offer(account_, offerSequence))) + if (auto sleOffer = view().peek(keylet::offer(accountID_, offerSequence))) { JLOG(j_.debug()) << "Trying to cancel offer #" << offerSequence; return offerDelete(view(), sleOffer, ctx_.registry.journal("View")); diff --git a/src/libxrpl/tx/transactors/dex/OfferCreate.cpp b/src/libxrpl/tx/transactors/dex/OfferCreate.cpp index b659b1a8c7..f3d03f5ccc 100644 --- a/src/libxrpl/tx/transactors/dex/OfferCreate.cpp +++ b/src/libxrpl/tx/transactors/dex/OfferCreate.cpp @@ -138,11 +138,11 @@ OfferCreate::preclaim(PreclaimContext const& ctx) auto const cancelSequence = ctx.tx[~sfOfferSequence]; - auto const sleCreator = ctx.view.read(keylet::account(id)); - if (!sleCreator) + AccountRoot const acctCreator(id, ctx.view); + if (!acctCreator) return terNO_ACCOUNT; - std::uint32_t const uAccountSequence = sleCreator->getFieldU32(sfSequence); + std::uint32_t const uAccountSequence = acctCreator->getFieldU32(sfSequence); auto viewJ = ctx.registry.journal("View"); AccountRoot wrappedPays(uPaysIssuerID, ctx.view); @@ -207,9 +207,9 @@ OfferCreate::checkAcceptAsset( // Only valid for custom currencies XRPL_ASSERT(!isXRP(issue.currency), "xrpl::OfferCreate::checkAcceptAsset : input is not XRP"); - auto const issuerAccount = view.read(keylet::account(issue.account)); + AccountRoot const issuerAcct(issue.account, view); - if (!issuerAccount) + if (!issuerAcct) { JLOG(j.debug()) << "delay: can't receive IOUs from non-existent issuer: " << to_string(issue.account); @@ -223,7 +223,7 @@ OfferCreate::checkAcceptAsset( if (issue.account == id) return tesSUCCESS; - if (((*issuerAccount)[sfFlags] & lsfRequireAuth) != 0u) + if (issuerAcct->getFlags() & lsfRequireAuth) { auto const trustLine = view.read(keylet::line(id, issue.account, issue.currency)); @@ -283,7 +283,7 @@ OfferCreate::flowCross( // cause a user's available balance to go to 0 (by causing it to dip // below the reserve) so we check this case again. STAmount const inStartBalance = - accountFunds(psb, account_, takerAmount.in, fhZERO_IF_FROZEN, j_); + accountFunds(psb, accountID_, takerAmount.in, fhZERO_IF_FROZEN, j_); if (inStartBalance <= beast::zero) { // The account balance can't cover even part of the offer. @@ -296,7 +296,7 @@ OfferCreate::flowCross( // offer taker. Set sendMax to allow for the gateway's cut. Rate gatewayXferRate{QUALITY_ONE}; STAmount sendMax = takerAmount.in; - if (!sendMax.native() && (account_ != sendMax.getIssuer())) + if (!sendMax.native() && (accountID_ != sendMax.getIssuer())) { WritableAccountRoot wrappedAcct(sendMax.getIssuer(), psb); gatewayXferRate = wrappedAcct.transferRate(); @@ -360,8 +360,8 @@ OfferCreate::flowCross( auto const result = flow( psb, deliver, - account_, - account_, + accountID_, + accountID_, paths, true, // default path (txFlags & tfFillOrKill) == 0u, // partial payment @@ -386,7 +386,7 @@ OfferCreate::flowCross( if (isTesSuccess(result.result())) { STAmount const takerInBalance = - accountFunds(psb, account_, takerAmount.in, fhZERO_IF_FROZEN, j_); + accountFunds(psb, accountID_, takerAmount.in, fhZERO_IF_FROZEN, j_); if (takerInBalance <= beast::zero) { @@ -546,7 +546,7 @@ OfferCreate::applyGuts(Sandbox& sb, Sandbox& sbCancel) // Process a cancellation request that's passed along with an offer. if (cancelSequence) { - auto const sleCancel = sb.peek(keylet::offer(account_, *cancelSequence)); + auto const sleCancel = sb.peek(keylet::offer(accountID_, *cancelSequence)); // It's not an error to not find the offer to cancel: it might have // been consumed or removed. If it is found, however, it's an error @@ -579,15 +579,15 @@ OfferCreate::applyGuts(Sandbox& sb, Sandbox& sbCancel) std::uint8_t uTickSize = Quality::maxTickSize; if (!isXRP(uPaysIssuerID)) { - auto const sle = sb.read(keylet::account(uPaysIssuerID)); - if (sle && sle->isFieldPresent(sfTickSize)) - uTickSize = std::min(uTickSize, (*sle)[sfTickSize]); + AccountRoot const acctPays(uPaysIssuerID, sb); + if (acctPays && acctPays->isFieldPresent(sfTickSize)) + uTickSize = std::min(uTickSize, (*acctPays)[sfTickSize]); } if (!isXRP(uGetsIssuerID)) { - auto const sle = sb.read(keylet::account(uGetsIssuerID)); - if (sle && sle->isFieldPresent(sfTickSize)) - uTickSize = std::min(uTickSize, (*sle)[sfTickSize]); + AccountRoot const acctGets(uGetsIssuerID, sb); + if (acctGets && acctGets->isFieldPresent(sfTickSize)) + uTickSize = std::min(uTickSize, (*acctGets)[sfTickSize]); } if (uTickSize < Quality::maxTickSize) { @@ -735,7 +735,7 @@ OfferCreate::applyGuts(Sandbox& sb, Sandbox& sbCancel) return {tesSUCCESS, true}; } - WritableAccountRoot wrappedCreator(account_, sb); + WritableAccountRoot wrappedCreator(accountID_, sb); if (!wrappedCreator) return {tefINTERNAL, false}; @@ -760,11 +760,11 @@ OfferCreate::applyGuts(Sandbox& sb, Sandbox& sbCancel) } // We need to place the remainder of the offer into its order book. - auto const offer_index = keylet::offer(account_, offerSequence); + auto const offer_index = keylet::offer(accountID_, offerSequence); // Add offer to owner's directory. auto const ownerNode = - sb.dirInsert(keylet::ownerDir(account_), offer_index, describeOwnerDir(account_)); + sb.dirInsert(keylet::ownerDir(accountID_), offer_index, describeOwnerDir(accountID_)); if (!ownerNode) { @@ -821,7 +821,7 @@ OfferCreate::applyGuts(Sandbox& sb, Sandbox& sbCancel) } auto sleOffer = std::make_shared(offer_index); - sleOffer->setAccountID(sfAccount, account_); + sleOffer->setAccountID(sfAccount, accountID_); sleOffer->setFieldU32(sfSequence, offerSequence); sleOffer->setFieldH256(sfBookDirectory, dir.key); sleOffer->setFieldAmount(sfTakerPays, saTakerPays); diff --git a/src/libxrpl/tx/transactors/did/DIDDelete.cpp b/src/libxrpl/tx/transactors/did/DIDDelete.cpp index d0599bf6e9..28fe345b72 100644 --- a/src/libxrpl/tx/transactors/did/DIDDelete.cpp +++ b/src/libxrpl/tx/transactors/did/DIDDelete.cpp @@ -53,7 +53,7 @@ DIDDelete::deleteSLE( TER DIDDelete::doApply() { - return deleteSLE(ctx_, keylet::did(account_), account_); + return deleteSLE(ctx_, keylet::did(accountID_), accountID_); } } // namespace xrpl diff --git a/src/libxrpl/tx/transactors/did/DIDSet.cpp b/src/libxrpl/tx/transactors/did/DIDSet.cpp index a805cf0a3a..8cb348d4b1 100644 --- a/src/libxrpl/tx/transactors/did/DIDSet.cpp +++ b/src/libxrpl/tx/transactors/did/DIDSet.cpp @@ -85,7 +85,7 @@ TER DIDSet::doApply() { // Edit ledger object if it already exists - Keylet const didKeylet = keylet::did(account_); + Keylet const didKeylet = keylet::did(accountID_); if (auto const sleDID = ctx_.view().peek(didKeylet)) { auto update = [&](auto const& sField) { @@ -116,7 +116,7 @@ DIDSet::doApply() // Create new ledger object otherwise auto const sleDID = std::make_shared(didKeylet); - (*sleDID)[sfAccount] = account_; + (*sleDID)[sfAccount] = accountID_; auto set = [&](auto const& sField) { if (auto const field = ctx_.tx[~sField]; field && !field->empty()) @@ -132,7 +132,7 @@ DIDSet::doApply() return tecEMPTY_DID; } - return addSLE(ctx_, sleDID, account_); + return addSLE(ctx_, sleDID, accountID_); } } // namespace xrpl diff --git a/src/libxrpl/tx/transactors/escrow/EscrowCancel.cpp b/src/libxrpl/tx/transactors/escrow/EscrowCancel.cpp index a27bc0d500..8d4ec12abe 100644 --- a/src/libxrpl/tx/transactors/escrow/EscrowCancel.cpp +++ b/src/libxrpl/tx/transactors/escrow/EscrowCancel.cpp @@ -163,7 +163,7 @@ EscrowCancel::doApply() return temDISABLED; // LCOV_EXCL_LINE auto const issuer = amount.getIssuer(); - bool const createAsset = account == account_; + bool const createAsset = account == accountID_; if (auto const ret = std::visit( [&](T const&) { return escrowUnlockApplyHelper( diff --git a/src/libxrpl/tx/transactors/escrow/EscrowCreate.cpp b/src/libxrpl/tx/transactors/escrow/EscrowCreate.cpp index 218a8b44bc..82c0161531 100644 --- a/src/libxrpl/tx/transactors/escrow/EscrowCreate.cpp +++ b/src/libxrpl/tx/transactors/escrow/EscrowCreate.cpp @@ -169,10 +169,10 @@ escrowCreatePreclaimHelper( return tecNO_PERMISSION; // If the lsfAllowTrustLineLocking is not enabled, return tecNO_PERMISSION - auto const sleIssuer = ctx.view.read(keylet::account(issuer)); - if (!sleIssuer) + AccountRoot const acctIssuer(issuer, ctx.view); + if (!acctIssuer) return tecNO_ISSUER; - if (!sleIssuer->isFlag(lsfAllowTrustLineLocking)) + if (!acctIssuer->isFlag(lsfAllowTrustLineLocking)) return tecNO_PERMISSION; // If the account does not have a trustline to the issuer, return tecNO_LINE @@ -304,15 +304,15 @@ EscrowCreate::preclaim(PreclaimContext const& ctx) AccountID const account{ctx.tx[sfAccount]}; AccountID const dest{ctx.tx[sfDestination]}; - auto const sled = ctx.view.read(keylet::account(dest)); - if (!sled) + AccountRoot const acctDest(dest, ctx.view); + if (!acctDest) return tecNO_DST; // Pseudo-accounts cannot receive escrow. Note, this is not amendment-gated // because all writes to pseudo-account discriminator fields **are** // amendment gated, hence the behaviour of this check will always match the // currently active amendments. - if (isPseudoAccount(sled)) + if (acctDest.isPseudoAccount()) return tecNO_PERMISSION; if (!isXRP(amount)) @@ -389,7 +389,7 @@ EscrowCreate::doApply() if (ctx_.tx[~sfFinishAfter] && after(closeTime, ctx_.tx[sfFinishAfter])) return tecNO_PERMISSION; - WritableAccountRoot wrappedAcct(account_, ctx_.view()); + WritableAccountRoot wrappedAcct(accountID_, ctx_.view()); if (!wrappedAcct) return tefINTERNAL; // LCOV_EXCL_LINE @@ -398,7 +398,7 @@ EscrowCreate::doApply() auto const reserve = ctx_.view().fees().accountReserve((*wrappedAcct)[sfOwnerCount] + 1); - auto const balance = sle->getFieldAmount(sfBalance).xrp(); + auto const balance = wrappedAcct->getFieldAmount(sfBalance).xrp(); if (balance < reserve) return tecINSUFFICIENT_RESERVE; @@ -411,19 +411,19 @@ EscrowCreate::doApply() // Check destination account { - auto const sled = ctx_.view().read(keylet::account(ctx_.tx[sfDestination])); - if (!sled) + AccountRoot const acctDest(ctx_.tx[sfDestination], ctx_.view()); + if (!acctDest) return tecNO_DST; // LCOV_EXCL_LINE - if ((((*sled)[sfFlags] & lsfRequireDestTag) != 0u) && !ctx_.tx[~sfDestinationTag]) + if ((acctDest->getFlags() & lsfRequireDestTag) && !ctx_.tx[~sfDestinationTag]) return tecDST_TAG_NEEDED; } // Create escrow in ledger. Note that we we use the value from the // sequence or ticket. For more explanation see comments in SeqProxy.h. - Keylet const escrowKeylet = keylet::escrow(account_, ctx_.tx.getSeqValue()); + Keylet const escrowKeylet = keylet::escrow(accountID_, ctx_.tx.getSeqValue()); auto const slep = std::make_shared(escrowKeylet); (*slep)[sfAmount] = amount; - (*slep)[sfAccount] = account_; + (*slep)[sfAccount] = accountID_; (*slep)[~sfCondition] = ctx_.tx[~sfCondition]; (*slep)[~sfSourceTag] = ctx_.tx[~sfSourceTag]; (*slep)[sfDestination] = ctx_.tx[sfDestination]; @@ -448,7 +448,7 @@ EscrowCreate::doApply() // Add escrow to sender's owner directory { auto page = ctx_.view().dirInsert( - keylet::ownerDir(account_), escrowKeylet, describeOwnerDir(account_)); + keylet::ownerDir(accountID_), escrowKeylet, describeOwnerDir(accountID_)); if (!page) return tecDIR_FULL; // LCOV_EXCL_LINE (*slep)[sfOwnerNode] = *page; @@ -456,7 +456,7 @@ EscrowCreate::doApply() // If it's not a self-send, add escrow to recipient's owner directory. AccountID const dest = ctx_.tx[sfDestination]; - if (dest != account_) + if (dest != accountID_) { auto page = ctx_.view().dirInsert(keylet::ownerDir(dest), escrowKeylet, describeOwnerDir(dest)); @@ -469,7 +469,7 @@ EscrowCreate::doApply() // track the total locked balance. For MPT, this isn't necessary because the // locked balance is already stored directly in the MPTokenIssuance object. AccountID const issuer = amount.getIssuer(); - if (!isXRP(amount) && issuer != account_ && issuer != dest && !amount.holds()) + if (!isXRP(amount) && issuer != accountID_ && issuer != dest && !amount.holds()) { auto page = ctx_.view().dirInsert(keylet::ownerDir(issuer), escrowKeylet, describeOwnerDir(issuer)); @@ -487,7 +487,7 @@ EscrowCreate::doApply() { if (auto const ret = std::visit( [&](T const&) { - return escrowLockApplyHelper(ctx_.view(), issuer, account_, amount, j_); + return escrowLockApplyHelper(ctx_.view(), issuer, accountID_, amount, j_); }, amount.asset().value()); !isTesSuccess(ret)) diff --git a/src/libxrpl/tx/transactors/escrow/EscrowFinish.cpp b/src/libxrpl/tx/transactors/escrow/EscrowFinish.cpp index b57a012035..07945fe2d7 100644 --- a/src/libxrpl/tx/transactors/escrow/EscrowFinish.cpp +++ b/src/libxrpl/tx/transactors/escrow/EscrowFinish.cpp @@ -289,11 +289,11 @@ EscrowFinish::doApply() // NOTE: Escrow payments cannot be used to fund accounts. AccountID const destID = (*slep)[sfDestination]; - auto const sled = ctx_.view().peek(keylet::account(destID)); - if (!sled) + WritableAccountRoot dest(destID, ctx_.view()); + if (!dest.exists()) return tecNO_DST; - if (auto err = verifyDepositPreauth(ctx_.tx, ctx_.view(), account_, destID, sled, ctx_.journal); + if (auto err = verifyDepositPreauth(ctx_.tx, ctx_.view(), accountID_, dest, ctx_.journal); !isTesSuccess(err)) return err; @@ -327,7 +327,7 @@ EscrowFinish::doApply() // Transfer amount to destination if (isXRP(amount)) { - (*sled)[sfBalance] = (*sled)[sfBalance] + amount; + (*dest)[sfBalance] = (*dest)[sfBalance] + amount; } else { @@ -338,13 +338,13 @@ EscrowFinish::doApply() ? xrpl::Rate(slep->getFieldU32(sfTransferRate)) : parityRate; auto const issuer = amount.getIssuer(); - bool const createAsset = destID == account_; + bool const createAsset = destID == accountID_; if (auto const ret = std::visit( [&](T const&) { return escrowUnlockApplyHelper( ctx_.view(), lockedRate, - sled, + dest, preFeeBalance_, amount, issuer, @@ -370,7 +370,7 @@ EscrowFinish::doApply() } } - ctx_.view().update(sled); + dest.update(); // Adjust source owner count WritableAccountRoot wrappedAcct(account, ctx_.view()); diff --git a/src/libxrpl/tx/transactors/escrow/EscrowHelpers.h b/src/libxrpl/tx/transactors/escrow/EscrowHelpers.h index 8a874b0529..32ba6e56d2 100644 --- a/src/libxrpl/tx/transactors/escrow/EscrowHelpers.h +++ b/src/libxrpl/tx/transactors/escrow/EscrowHelpers.h @@ -21,7 +21,7 @@ TER escrowUnlockApplyHelper( ApplyView& view, Rate lockedRate, - std::variant, WritableAccountRoot> sleDest, + std::variant, WritableAccountRoot> dest, STAmount const& xrpBalance, STAmount const& amount, AccountID const& issuer, @@ -35,7 +35,7 @@ inline TER escrowUnlockApplyHelper( ApplyView& view, Rate lockedRate, - std::variant, WritableAccountRoot> sleDest, + std::variant, WritableAccountRoot> dest, STAmount const& xrpBalance, STAmount const& amount, AccountID const& issuer, @@ -57,11 +57,11 @@ escrowUnlockApplyHelper( if (!view.exists(trustLineKey) && createAsset) { - // For backwards compatibility: if sleDest is not WritableAccountRoot, return error - if (!std::holds_alternative(sleDest)) + // For backwards compatibility: if dest is not WritableAccountRoot, return error + if (!std::holds_alternative(dest)) return tefEXCEPTION; - auto& wrappedDest = std::get(sleDest); + auto& wrappedDest = std::get(dest); // Can the account cover the trust line's reserve? if (std::uint32_t const ownerCount = {wrappedDest->at(sfOwnerCount)}; @@ -171,7 +171,7 @@ inline TER escrowUnlockApplyHelper( ApplyView& view, Rate lockedRate, - std::variant, WritableAccountRoot> sleDest, + std::variant, WritableAccountRoot> dest, STAmount const& xrpBalance, STAmount const& amount, AccountID const& issuer, @@ -187,11 +187,11 @@ escrowUnlockApplyHelper( auto const issuanceKey = keylet::mptIssuance(mptID); if (!view.exists(keylet::mptoken(issuanceKey.key, receiver)) && createAsset && !receiverIssuer) { - // For backwards compatibility: if sleDest is not WritableAccountRoot, return error - if (!std::holds_alternative(sleDest)) + // For backwards compatibility: if dest is not WritableAccountRoot, return error + if (!std::holds_alternative(dest)) return tefEXCEPTION; - auto& wrappedDest = std::get(sleDest); + auto& wrappedDest = std::get(dest); if (std::uint32_t const ownerCount = {wrappedDest->at(sfOwnerCount)}; xrpBalance < view.fees().accountReserve(ownerCount + 1)) diff --git a/src/libxrpl/tx/transactors/lending/LoanBrokerCoverClawback.cpp b/src/libxrpl/tx/transactors/lending/LoanBrokerCoverClawback.cpp index 24aa3f8bf2..dd6eab8ffc 100644 --- a/src/libxrpl/tx/transactors/lending/LoanBrokerCoverClawback.cpp +++ b/src/libxrpl/tx/transactors/lending/LoanBrokerCoverClawback.cpp @@ -1,6 +1,7 @@ #include // #include +#include #include #include @@ -81,16 +82,16 @@ determineBrokerID(ReadView const& view, STTx const& tx) // Thus, Amount.issuer _should_ be the loan broker's // pseudo-account, but we don't know yet whether it is. auto const maybePseudo = dstAmount->getIssuer(); - auto const sle = view.read(keylet::account(maybePseudo)); + AccountRoot const acct(maybePseudo, view); // If the account was not found, the transaction can't go further. - if (!sle) + if (!acct) return Unexpected{tecNO_ENTRY}; // If the account was found, and has a LoanBrokerID (and therefore // is a pseudo-account), that's the // answer we need. - if (auto const brokerID = sle->at(~sfLoanBrokerID)) + if (auto const brokerID = acct->at(~sfLoanBrokerID)) return *brokerID; // If the account does not have a LoanBrokerID, the transaction @@ -273,8 +274,8 @@ LoanBrokerCoverClawback::preclaim(PreclaimContext const& ctx) return tecINTERNAL; // tecINSUFFICIENT_FUNDS; LCOV_EXCL_LINE // Check if the vault asset issuer has the correct flags - auto const sleIssuer = ctx.view.read(keylet::account(vaultAsset.getIssuer())); - if (!sleIssuer) + AccountRoot const acctIssuer(vaultAsset.getIssuer(), ctx.view); + if (!acctIssuer) { // LCOV_EXCL_START JLOG(ctx.j.fatal()) << "Issuer account does not exist."; @@ -283,7 +284,7 @@ LoanBrokerCoverClawback::preclaim(PreclaimContext const& ctx) } return std::visit( - [&](T const&) { return preclaimHelper(ctx, *sleIssuer, clawAmount); }, + [&](T const&) { return preclaimHelper(ctx, *acctIssuer.sle(), clawAmount); }, vaultAsset.value()); } diff --git a/src/libxrpl/tx/transactors/lending/LoanBrokerCoverDeposit.cpp b/src/libxrpl/tx/transactors/lending/LoanBrokerCoverDeposit.cpp index 4630e6a360..fff9619be0 100644 --- a/src/libxrpl/tx/transactors/lending/LoanBrokerCoverDeposit.cpp +++ b/src/libxrpl/tx/transactors/lending/LoanBrokerCoverDeposit.cpp @@ -109,7 +109,8 @@ LoanBrokerCoverDeposit::doApply() auto const brokerPseudoID = broker->at(sfAccount); // Transfer assets from depositor to pseudo-account. - if (auto ter = accountSend(view(), account_, brokerPseudoID, amount, j_, WaiveTransferFee::Yes)) + if (auto ter = + accountSend(view(), accountID_, brokerPseudoID, amount, j_, WaiveTransferFee::Yes)) return ter; // Increase the LoanBroker's CoverAvailable by Amount diff --git a/src/libxrpl/tx/transactors/lending/LoanBrokerCoverWithdraw.cpp b/src/libxrpl/tx/transactors/lending/LoanBrokerCoverWithdraw.cpp index 6946992376..ea33fd2761 100644 --- a/src/libxrpl/tx/transactors/lending/LoanBrokerCoverWithdraw.cpp +++ b/src/libxrpl/tx/transactors/lending/LoanBrokerCoverWithdraw.cpp @@ -149,7 +149,7 @@ LoanBrokerCoverWithdraw::doApply() auto const brokerID = tx[sfLoanBrokerID]; auto const amount = tx[sfAmount]; - auto const dstAcct = tx[~sfDestination].value_or(account_); + auto const dstAcct = tx[~sfDestination].value_or(accountID_); auto broker = view().peek(keylet::loanbroker(brokerID)); if (!broker) @@ -169,7 +169,7 @@ LoanBrokerCoverWithdraw::doApply() associateAsset(*broker, vaultAsset); - return doWithdraw(view(), tx, account_, dstAcct, brokerPseudoID, preFeeBalance_, amount, j_); + return doWithdraw(view(), tx, accountID_, dstAcct, brokerPseudoID, preFeeBalance_, amount, j_); } //------------------------------------------------------------------------------ diff --git a/src/libxrpl/tx/transactors/lending/LoanBrokerDelete.cpp b/src/libxrpl/tx/transactors/lending/LoanBrokerDelete.cpp index 3b36f0943f..23766125a4 100644 --- a/src/libxrpl/tx/transactors/lending/LoanBrokerDelete.cpp +++ b/src/libxrpl/tx/transactors/lending/LoanBrokerDelete.cpp @@ -115,7 +115,7 @@ LoanBrokerDelete::doApply() auto const brokerPseudoID = broker->at(sfAccount); if (!view().dirRemove( - keylet::ownerDir(account_), broker->at(sfOwnerNode), broker->key(), false)) + keylet::ownerDir(accountID_), broker->at(sfOwnerNode), broker->key(), false)) { return tefBAD_LEDGER; // LCOV_EXCL_LINE } @@ -128,25 +128,25 @@ LoanBrokerDelete::doApply() { auto const coverAvailable = STAmount{vaultAsset, broker->at(sfCoverAvailable)}; if (auto const ter = accountSend( - view(), brokerPseudoID, account_, coverAvailable, j_, WaiveTransferFee::Yes)) + view(), brokerPseudoID, accountID_, coverAvailable, j_, WaiveTransferFee::Yes)) return ter; } if (auto ter = removeEmptyHolding(view(), brokerPseudoID, vaultAsset, j_)) return ter; - auto brokerPseudoSLE = view().peek(keylet::account(brokerPseudoID)); - if (!brokerPseudoSLE) + WritableAccountRoot brokerPseudo(brokerPseudoID, view()); + if (!brokerPseudo) return tefBAD_LEDGER; // LCOV_EXCL_LINE // Making the payment and removing the empty holding should have deleted any // obligations associated with the broker or broker pseudo-account. - if (*brokerPseudoSLE->at(sfBalance)) + if (*brokerPseudo->at(sfBalance)) { JLOG(j_.warn()) << "LoanBrokerDelete: Pseudo-account has a balance"; return tecHAS_OBLIGATIONS; // LCOV_EXCL_LINE } - if (brokerPseudoSLE->at(sfOwnerCount) != 0) + if (brokerPseudo->at(sfOwnerCount) != 0) { JLOG(j_.warn()) << "LoanBrokerDelete: Pseudo-account still owns objects"; return tecHAS_OBLIGATIONS; // LCOV_EXCL_LINE @@ -157,12 +157,12 @@ LoanBrokerDelete::doApply() return tecHAS_OBLIGATIONS; // LCOV_EXCL_LINE } - view().erase(brokerPseudoSLE); + brokerPseudo.erase(); view().erase(broker); { - WritableAccountRoot wrappedOwner(account_, view()); + WritableAccountRoot wrappedOwner(accountID_, view()); if (!wrappedOwner) return tefBAD_LEDGER; // LCOV_EXCL_LINE diff --git a/src/libxrpl/tx/transactors/lending/LoanBrokerSet.cpp b/src/libxrpl/tx/transactors/lending/LoanBrokerSet.cpp index 362df496df..c9f8a3d4de 100644 --- a/src/libxrpl/tx/transactors/lending/LoanBrokerSet.cpp +++ b/src/libxrpl/tx/transactors/lending/LoanBrokerSet.cpp @@ -202,7 +202,7 @@ LoanBrokerSet::doApply() auto const vaultAsset = sleVault->at(sfAsset); auto const sequence = tx.getSeqValue(); - WritableAccountRoot owner(account_, view); + WritableAccountRoot owner(accountID_, view); if (!owner) { // This should be impossible @@ -211,9 +211,9 @@ LoanBrokerSet::doApply() return tefBAD_LEDGER; // LCOV_EXCL_STOP } - auto broker = std::make_shared(keylet::loanbroker(account_, sequence)); + auto broker = std::make_shared(keylet::loanbroker(accountID_, sequence)); - if (auto const ter = dirLink(view, account_, broker)) + if (auto const ter = dirLink(view, accountID_, broker)) return ter; // LCOV_EXCL_LINE if (auto const ter = dirLink(view, vaultPseudoID, broker, sfVaultNode)) return ter; // LCOV_EXCL_LINE @@ -237,7 +237,7 @@ LoanBrokerSet::doApply() // Initialize data fields: broker->at(sfSequence) = sequence; broker->at(sfVaultID) = vaultID; - broker->at(sfOwner) = account_; + broker->at(sfOwner) = accountID_; broker->at(sfAccount) = pseudoId; // The LoanSequence indexes loans created by this broker, starting at 1 broker->at(sfLoanSequence) = 1; diff --git a/src/libxrpl/tx/transactors/lending/LoanPay.cpp b/src/libxrpl/tx/transactors/lending/LoanPay.cpp index 8739cb645a..eaf0b2caad 100644 --- a/src/libxrpl/tx/transactors/lending/LoanPay.cpp +++ b/src/libxrpl/tx/transactors/lending/LoanPay.cpp @@ -2,6 +2,7 @@ // #include #include +#include #include #include #include @@ -286,7 +287,7 @@ LoanPay::doApply() }(); auto const brokerPayee = sendBrokerFeeToOwner ? brokerOwner : brokerPseudoAccount; - auto const brokerPayeeSle = view.peek(keylet::account(brokerPayee)); + WritableAccountRoot brokerPayeeAcct(brokerPayee, view); if (!sendBrokerFeeToOwner) { // If we can't send the fee to the owner, and the pseudo-account is @@ -488,13 +489,13 @@ LoanPay::doApply() #if !NDEBUG auto const accountBalanceBefore = accountHolds( view, - account_, + accountID_, asset, fhIGNORE_FREEZE, ahIGNORE_AUTH, j_, SpendableHandling::shFULL_BALANCE); - auto const vaultBalanceBefore = account_ == vaultPseudoAccount + auto const vaultBalanceBefore = accountID_ == vaultPseudoAccount ? STAmount{asset, 0} : accountHolds( view, @@ -504,7 +505,7 @@ LoanPay::doApply() ahIGNORE_AUTH, j_, SpendableHandling::shFULL_BALANCE); - auto const brokerBalanceBefore = account_ == brokerPayee + auto const brokerBalanceBefore = accountID_ == brokerPayee ? STAmount{asset, 0} : accountHolds( view, @@ -524,11 +525,11 @@ LoanPay::doApply() if (totalPaidToBroker != beast::zero) { - if (brokerPayee == account_) + if (brokerPayee == accountID_) { // The broker may have deleted their holding. Recreate it if needed if (auto const ter = addEmptyHolding( - view, brokerPayee, brokerPayeeSle->at(sfBalance).value().xrp(), asset, j_); + view, brokerPayee, brokerPayeeAcct->at(sfBalance).value().xrp(), asset, j_); ter && ter != tecDUPLICATE) { // ignore tecDUPLICATE. That means the holding already exists, @@ -542,7 +543,7 @@ LoanPay::doApply() if (auto const ter = accountSendMulti( view, - account_, + accountID_, asset, {{vaultPseudoAccount, totalPaidToVaultRounded}, {brokerPayee, totalPaidToBroker}}, j_, @@ -565,13 +566,13 @@ LoanPay::doApply() auto const accountBalanceAfter = accountHolds( view, - account_, + accountID_, asset, fhIGNORE_FREEZE, ahIGNORE_AUTH, j_, SpendableHandling::shFULL_BALANCE); - auto const vaultBalanceAfter = account_ == vaultPseudoAccount + auto const vaultBalanceAfter = accountID_ == vaultPseudoAccount ? STAmount{asset, 0} : accountHolds( view, @@ -581,7 +582,7 @@ LoanPay::doApply() ahIGNORE_AUTH, j_, SpendableHandling::shFULL_BALANCE); - auto const brokerBalanceAfter = account_ == brokerPayee + auto const brokerBalanceAfter = accountID_ == brokerPayee ? STAmount{asset, 0} : accountHolds( view, @@ -600,7 +601,7 @@ LoanPay::doApply() XRPL_ASSERT_PARTS( accountBalanceAfter >= beast::zero, "xrpl::LoanPay::doApply", "positive account balance"); XRPL_ASSERT_PARTS( - accountBalanceAfter < accountBalanceBefore || account_ == asset.getIssuer(), + accountBalanceAfter < accountBalanceBefore || accountID_ == asset.getIssuer(), "xrpl::LoanPay::doApply", "account balance decreased"); XRPL_ASSERT_PARTS( diff --git a/src/libxrpl/tx/transactors/lending/LoanSet.cpp b/src/libxrpl/tx/transactors/lending/LoanSet.cpp index 56cdf121bb..c1eb843c20 100644 --- a/src/libxrpl/tx/transactors/lending/LoanSet.cpp +++ b/src/libxrpl/tx/transactors/lending/LoanSet.cpp @@ -348,8 +348,8 @@ LoanSet::doApply() if (!brokerSle) return tefBAD_LEDGER; // LCOV_EXCL_LINE auto const brokerOwner = brokerSle->at(sfOwner); - auto const brokerOwnerSle = view.peek(keylet::account(brokerOwner)); - if (!brokerOwnerSle) + WritableAccountRoot brokerOwnerAcct(brokerOwner, view); + if (!brokerOwnerAcct) return tefBAD_LEDGER; // LCOV_EXCL_LINE auto const vaultSle = view.peek(keylet ::vault(brokerSle->at(sfVaultID))); @@ -359,7 +359,7 @@ LoanSet::doApply() Asset const vaultAsset = vaultSle->at(sfAsset); auto const counterparty = tx[~sfCounterparty].value_or(brokerOwner); - auto const borrower = counterparty == brokerOwner ? account_ : counterparty; + auto const borrower = counterparty == brokerOwner ? accountID_ : counterparty; WritableAccountRoot wrappedBorrower(borrower, view); if (!wrappedBorrower) { @@ -367,8 +367,8 @@ LoanSet::doApply() } auto const brokerPseudo = brokerSle->at(sfAccount); - auto const brokerPseudoSle = view.peek(keylet::account(brokerPseudo)); - if (!brokerPseudoSle) + WritableAccountRoot brokerPseudoAcct(brokerPseudo, view); + if (!brokerPseudoAcct) { return tefBAD_LEDGER; // LCOV_EXCL_LINE } @@ -478,7 +478,7 @@ LoanSet::doApply() { auto const ownerCount = wrappedBorrower->at(sfOwnerCount); auto const balance = - account_ == borrower ? preFeeBalance_ : wrappedBorrower->at(sfBalance).value().xrp(); + accountID_ == borrower ? preFeeBalance_ : wrappedBorrower->at(sfBalance).value().xrp(); if (balance < view.fees().accountReserve(ownerCount)) return tecINSUFFICIENT_RESERVE; } @@ -490,7 +490,7 @@ LoanSet::doApply() // Create a holding for the borrower if one does not already exist. XRPL_ASSERT_PARTS( - borrower == account_ || borrower == counterparty, + borrower == accountID_ || borrower == counterparty, "xrpl::LoanSet::doApply", "borrower signed transaction"); if (auto const ter = addEmptyHolding( @@ -512,12 +512,12 @@ LoanSet::doApply() // Create the holding if it doesn't already exist (necessary for MPTs). // The owner may have deleted their MPT / line at some point. XRPL_ASSERT_PARTS( - brokerOwner == account_ || brokerOwner == counterparty, + brokerOwner == accountID_ || brokerOwner == counterparty, "xrpl::LoanSet::doApply", "broker owner signed transaction"); if (auto const ter = addEmptyHolding( - view, brokerOwner, brokerOwnerSle->at(sfBalance).value().xrp(), vaultAsset, j_); + view, brokerOwner, brokerOwnerAcct->at(sfBalance).value().xrp(), vaultAsset, j_); ter && ter != tecDUPLICATE) { // ignore tecDUPLICATE. That means the holding already exists, diff --git a/src/libxrpl/tx/transactors/nft/NFTokenAcceptOffer.cpp b/src/libxrpl/tx/transactors/nft/NFTokenAcceptOffer.cpp index 15a745b8dd..7414c26ac4 100644 --- a/src/libxrpl/tx/transactors/nft/NFTokenAcceptOffer.cpp +++ b/src/libxrpl/tx/transactors/nft/NFTokenAcceptOffer.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -348,11 +349,11 @@ NFTokenAcceptOffer::transferNFToken( !isTesSuccess(ret)) return ret; - auto const sleBuyer = view().read(keylet::account(buyer)); - if (!sleBuyer) + AccountRoot const acctBuyer(buyer, view()); + if (!acctBuyer) return tecINTERNAL; // LCOV_EXCL_LINE - std::uint32_t const buyerOwnerCountBefore = sleBuyer->getFieldU32(sfOwnerCount); + std::uint32_t const buyerOwnerCountBefore = acctBuyer->getFieldU32(sfOwnerCount); auto const insertRet = nft::insertToken(view(), buyer, std::move(tokenAndPage->token)); @@ -369,9 +370,9 @@ NFTokenAcceptOffer::transferNFToken( // the deduction of the potential offer price. A small caveat here is // that the balance has already deducted the transaction fee, meaning // that the reserve requirement is a few drops higher. - auto const buyerBalance = sleBuyer->getFieldAmount(sfBalance); + auto const buyerBalance = acctBuyer->getFieldAmount(sfBalance); - auto const buyerOwnerCountAfter = sleBuyer->getFieldU32(sfOwnerCount); + auto const buyerOwnerCountAfter = acctBuyer->getFieldU32(sfOwnerCount); if (buyerOwnerCountAfter > buyerOwnerCountBefore) { if (auto const reserve = view().fees().accountReserve(buyerOwnerCountAfter); @@ -388,8 +389,8 @@ NFTokenAcceptOffer::acceptOffer(std::shared_ptr const& offer) { bool const isSell = offer->isFlag(lsfSellNFToken); AccountID const owner = (*offer)[sfOwner]; - AccountID const& seller = isSell ? owner : account_; - AccountID const& buyer = isSell ? account_ : owner; + AccountID const& seller = isSell ? owner : accountID_; + AccountID const& buyer = isSell ? accountID_ : owner; auto const nftokenID = (*offer)[sfNFTokenID]; @@ -510,7 +511,7 @@ NFTokenAcceptOffer::doApply() // Send the broker the amount they requested. if (auto const cut = ctx_.tx[~sfNFTokenBrokerFee]; cut && cut.value() != beast::zero) { - if (auto const r = pay(buyer, account_, cut.value()); !isTesSuccess(r)) + if (auto const r = pay(buyer, accountID_, cut.value()); !isTesSuccess(r)) return r; amount -= cut.value(); diff --git a/src/libxrpl/tx/transactors/nft/NFTokenBurn.cpp b/src/libxrpl/tx/transactors/nft/NFTokenBurn.cpp index 5a31e35470..c552052f6a 100644 --- a/src/libxrpl/tx/transactors/nft/NFTokenBurn.cpp +++ b/src/libxrpl/tx/transactors/nft/NFTokenBurn.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -34,9 +35,9 @@ NFTokenBurn::preclaim(PreclaimContext const& ctx) if (auto const issuer = nft::getIssuer(ctx.tx[sfNFTokenID]); issuer != account) { - if (auto const sle = ctx.view.read(keylet::account(issuer)); sle) + if (AccountRoot const acctIssuer(issuer, ctx.view); acctIssuer) { - if (auto const minter = (*sle)[~sfNFTokenMinter]; minter != account) + if (auto const minter = acctIssuer->at(~sfNFTokenMinter); minter != account) return tecNO_PERMISSION; } } @@ -59,10 +60,10 @@ NFTokenBurn::doApply() if (!isTesSuccess(ret)) return ret; - if (auto issuer = view().peek(keylet::account(nft::getIssuer(ctx_.tx[sfNFTokenID])))) + if (WritableAccountRoot issuer(nft::getIssuer(ctx_.tx[sfNFTokenID]), view()); issuer) { (*issuer)[~sfBurnedNFTokens] = (*issuer)[~sfBurnedNFTokens].value_or(0) + 1; - view().update(issuer); + issuer.update(); } // Delete up to 500 offers in total. diff --git a/src/libxrpl/tx/transactors/nft/NFTokenMint.cpp b/src/libxrpl/tx/transactors/nft/NFTokenMint.cpp index 7bebbd0070..4bfc85d2c3 100644 --- a/src/libxrpl/tx/transactors/nft/NFTokenMint.cpp +++ b/src/libxrpl/tx/transactors/nft/NFTokenMint.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -166,12 +167,12 @@ NFTokenMint::preclaim(PreclaimContext const& ctx) // transaction. Check that and verify that this is allowed: if (auto issuer = ctx.tx[~sfIssuer]) { - auto const sle = ctx.view.read(keylet::account(*issuer)); + AccountRoot const acctIssuer(*issuer, ctx.view); - if (!sle) + if (!acctIssuer) return tecNO_ISSUER; - if (auto const minter = (*sle)[~sfNFTokenMinter]; minter != ctx.tx[sfAccount]) + if (auto const minter = acctIssuer->at(~sfNFTokenMinter); minter != ctx.tx[sfAccount]) return tecNO_PERMISSION; } @@ -202,11 +203,11 @@ NFTokenMint::preclaim(PreclaimContext const& ctx) TER NFTokenMint::doApply() { - auto const issuer = ctx_.tx[~sfIssuer].value_or(account_); + auto const issuer = ctx_.tx[~sfIssuer].value_or(accountID_); auto const tokenSeq = [this, &issuer]() -> Expected { - auto const root = view().peek(keylet::account(issuer)); - if (root == nullptr) + WritableAccountRoot root(issuer, view()); + if (!root) { // Should not happen. Checked in preclaim. return Unexpected(tecNO_ISSUER); @@ -251,7 +252,7 @@ NFTokenMint::doApply() if (tokenSeq + 1u == 0u || tokenSeq < offset) return Unexpected(tecMAX_SEQUENCE_REACHED); - ctx_.view().update(root); + root.update(); return tokenSeq; }(); @@ -259,7 +260,7 @@ NFTokenMint::doApply() return (tokenSeq.error()); std::uint32_t const ownerCountBefore = - view().read(keylet::account(account_))->getFieldU32(sfOwnerCount); + AccountRoot(accountID_, view())->getFieldU32(sfOwnerCount); // Assemble the new NFToken. SOTemplate const* nfTokenTemplate = @@ -285,7 +286,7 @@ NFTokenMint::doApply() object.setFieldVL(sfURI, *uri); }); - if (TER const ret = nft::insertToken(ctx_.view(), account_, std::move(newToken)); + if (TER const ret = nft::insertToken(ctx_.view(), accountID_, std::move(newToken)); !isTesSuccess(ret)) return ret; @@ -312,8 +313,7 @@ NFTokenMint::doApply() // allows NFTs to be added to the page (and burn fees) without // requiring the reserve to be met each time. The reserve is // only managed when a new NFT page or sell offer is added. - if (auto const ownerCountAfter = - view().read(keylet::account(account_))->getFieldU32(sfOwnerCount); + if (auto const ownerCountAfter = AccountRoot(accountID_, view())->getFieldU32(sfOwnerCount); ownerCountAfter > ownerCountBefore) { if (auto const reserve = view().fees().accountReserve(ownerCountAfter); diff --git a/src/libxrpl/tx/transactors/nft/NFTokenModify.cpp b/src/libxrpl/tx/transactors/nft/NFTokenModify.cpp index 8ccd4e9552..b3bb66cbc4 100644 --- a/src/libxrpl/tx/transactors/nft/NFTokenModify.cpp +++ b/src/libxrpl/tx/transactors/nft/NFTokenModify.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -36,10 +37,10 @@ NFTokenModify::preclaim(PreclaimContext const& ctx) // Verify permissions for the issuer if (AccountID const issuer = nft::getIssuer(ctx.tx[sfNFTokenID]); issuer != account) { - auto const sle = ctx.view.read(keylet::account(issuer)); - if (!sle) + AccountRoot const acctIssuer(issuer, ctx.view); + if (!acctIssuer) return tecINTERNAL; // LCOV_EXCL_LINE - if (auto const minter = (*sle)[~sfNFTokenMinter]; minter != account) + if (auto const minter = acctIssuer->at(~sfNFTokenMinter); minter != account) return tecNO_PERMISSION; } diff --git a/src/libxrpl/tx/transactors/nft/NFTokenUtils.cpp b/src/libxrpl/tx/transactors/nft/NFTokenUtils.cpp index dc3c3a6693..6b8a8d0b88 100644 --- a/src/libxrpl/tx/transactors/nft/NFTokenUtils.cpp +++ b/src/libxrpl/tx/transactors/nft/NFTokenUtils.cpp @@ -856,10 +856,10 @@ tokenOfferCreatePreclaim( if (nftIssuer != acctID && ((nftFlags & nft::flagTransferable) == 0)) { - auto const root = view.read(keylet::account(nftIssuer)); - XRPL_ASSERT(root, "xrpl::nft::tokenOfferCreatePreclaim : non-null account"); + AccountRoot const acctRoot(nftIssuer, view); + XRPL_ASSERT(acctRoot, "xrpl::nft::tokenOfferCreatePreclaim : non-null account"); - if (auto minter = (*root)[~sfNFTokenMinter]; minter != acctID) + if (auto minter = acctRoot->at(~sfNFTokenMinter); minter != acctID) return tefNFTOKEN_IS_NOT_TRANSFERABLE; } @@ -881,26 +881,26 @@ tokenOfferCreatePreclaim( { // If a destination is specified, the destination must already be in // the ledger. - auto const sleDst = view.read(keylet::account(*dest)); + AccountRoot const acctDst(*dest, view); - if (!sleDst) + if (!acctDst) return tecNO_DST; // check if the destination has disallowed incoming offers - if ((sleDst->getFlags() & lsfDisallowIncomingNFTokenOffer) != 0u) + if (acctDst->getFlags() & lsfDisallowIncomingNFTokenOffer) return tecNO_PERMISSION; } if (owner) { - auto const sleOwner = view.read(keylet::account(*owner)); + AccountRoot const acctOwner(*owner, view); // defensively check // it should not be possible to specify owner that doesn't exist - if (!sleOwner) + if (!acctOwner) return tecNO_TARGET; - if ((sleOwner->getFlags() & lsfDisallowIncomingNFTokenOffer) != 0u) + if (acctOwner->getFlags() & lsfDisallowIncomingNFTokenOffer) return tecNO_PERMISSION; } @@ -932,9 +932,8 @@ tokenOfferCreateApply( beast::Journal j, std::uint32_t txFlags) { - Keylet const acctKeylet = keylet::account(acctID); - if (auto const acct = view.read(acctKeylet); - priorBalance < view.fees().accountReserve((*acct)[sfOwnerCount] + 1)) + AccountRoot const acctRoot(acctID, view); + if (priorBalance < view.fees().accountReserve(acctRoot->getFieldU32(sfOwnerCount) + 1)) return tecINSUFFICIENT_RESERVE; auto const offerID = keylet::nftoffer(acctID, seqProxy.value()); @@ -1004,8 +1003,8 @@ checkTrustlineAuthorized( if (view.rules().enabled(fixEnforceNFTokenTrustlineV2)) { - auto const issuerAccount = view.read(keylet::account(issue.account)); - if (!issuerAccount) + AccountRoot const acctIssuer(issue.account, view); + if (!acctIssuer) { JLOG(j.debug()) << "xrpl::nft::checkTrustlineAuthorized: can't " "receive IOUs from non-existent issuer: " @@ -1022,7 +1021,7 @@ checkTrustlineAuthorized( return tesSUCCESS; } - if (issuerAccount->isFlag(lsfRequireAuth)) + if (acctIssuer->isFlag(lsfRequireAuth)) { auto const trustLine = view.read(keylet::line(id, issue.account, issue.currency)); @@ -1056,8 +1055,8 @@ checkTrustlineDeepFrozen( if (view.rules().enabled(featureDeepFreeze)) { - auto const issuerAccount = view.read(keylet::account(issue.account)); - if (!issuerAccount) + AccountRoot const acctIssuer(issue.account, view); + if (!acctIssuer) { JLOG(j.debug()) << "xrpl::nft::checkTrustlineDeepFrozen: can't " "receive IOUs from non-existent issuer: " diff --git a/src/libxrpl/tx/transactors/oracle/OracleDelete.cpp b/src/libxrpl/tx/transactors/oracle/OracleDelete.cpp index 06aef98ffc..350231e9de 100644 --- a/src/libxrpl/tx/transactors/oracle/OracleDelete.cpp +++ b/src/libxrpl/tx/transactors/oracle/OracleDelete.cpp @@ -72,8 +72,8 @@ OracleDelete::deleteOracle( TER OracleDelete::doApply() { - if (auto sle = ctx_.view().peek(keylet::oracle(account_, ctx_.tx[sfOracleDocumentID]))) - return deleteOracle(ctx_.view(), sle, account_, j_); + if (auto sle = ctx_.view().peek(keylet::oracle(accountID_, ctx_.tx[sfOracleDocumentID]))) + return deleteOracle(ctx_.view(), sle, accountID_, j_); return tecINTERNAL; // LCOV_EXCL_LINE } diff --git a/src/libxrpl/tx/transactors/oracle/OracleSet.cpp b/src/libxrpl/tx/transactors/oracle/OracleSet.cpp index 197b2bdd50..3df5123033 100644 --- a/src/libxrpl/tx/transactors/oracle/OracleSet.cpp +++ b/src/libxrpl/tx/transactors/oracle/OracleSet.cpp @@ -42,8 +42,8 @@ OracleSet::preflight(PreflightContext const& ctx) TER OracleSet::preclaim(PreclaimContext const& ctx) { - auto const sleSetter = ctx.view.read(keylet::account(ctx.tx.getAccountID(sfAccount))); - if (!sleSetter) + AccountRoot const acctSetter(ctx.tx.getAccountID(sfAccount), ctx.view); + if (!acctSetter) return terNO_ACCOUNT; // LCOV_EXCL_LINE // lastUpdateTime must be within maxLastUpdateTimeDelta seconds @@ -150,8 +150,8 @@ OracleSet::preclaim(PreclaimContext const& ctx) return tecARRAY_TOO_LARGE; auto const reserve = - ctx.view.fees().accountReserve(sleSetter->getFieldU32(sfOwnerCount) + adjustReserve); - auto const& balance = sleSetter->getFieldAmount(sfBalance); + ctx.view.fees().accountReserve(acctSetter->getFieldU32(sfOwnerCount) + adjustReserve); + auto const& balance = acctSetter->getFieldAmount(sfBalance); if (balance < reserve) return tecINSUFFICIENT_RESERVE; @@ -182,7 +182,7 @@ setPriceDataInnerObjTemplate(STObject& obj) TER OracleSet::doApply() { - auto const oracleID = keylet::oracle(account_, ctx_.tx[sfOracleDocumentID]); + auto const oracleID = keylet::oracle(accountID_, ctx_.tx[sfOracleDocumentID]); auto populatePriceData = [](STObject& priceData, STObject const& entry) { setPriceDataInnerObjTemplate(priceData); @@ -292,7 +292,7 @@ OracleSet::doApply() sle->setFieldU32(sfLastUpdateTime, ctx_.tx[sfLastUpdateTime]); auto page = ctx_.view().dirInsert( - keylet::ownerDir(account_), sle->key(), describeOwnerDir(account_)); + keylet::ownerDir(accountID_), sle->key(), describeOwnerDir(accountID_)); if (!page) return tecDIR_FULL; // LCOV_EXCL_LINE diff --git a/src/libxrpl/tx/transactors/payment/DepositPreauth.cpp b/src/libxrpl/tx/transactors/payment/DepositPreauth.cpp index d361edce44..ab13dc143b 100644 --- a/src/libxrpl/tx/transactors/payment/DepositPreauth.cpp +++ b/src/libxrpl/tx/transactors/payment/DepositPreauth.cpp @@ -135,7 +135,7 @@ DepositPreauth::doApply() { if (ctx_.tx.isFieldPresent(sfAuthorize)) { - WritableAccountRoot wrappedOwner(account_, view()); + WritableAccountRoot wrappedOwner(accountID_, view()); if (!wrappedOwner) return {tefINTERNAL}; @@ -153,15 +153,15 @@ DepositPreauth::doApply() // Preclaim already verified that the Preauth entry does not yet exist. // Create and populate the Preauth entry. AccountID const auth{ctx_.tx[sfAuthorize]}; - Keylet const preauthKeylet = keylet::depositPreauth(account_, auth); + Keylet const preauthKeylet = keylet::depositPreauth(accountID_, auth); auto slePreauth = std::make_shared(preauthKeylet); - slePreauth->setAccountID(sfAccount, account_); + slePreauth->setAccountID(sfAccount, accountID_); slePreauth->setAccountID(sfAuthorize, auth); view().insert(slePreauth); - auto const page = - view().dirInsert(keylet::ownerDir(account_), preauthKeylet, describeOwnerDir(account_)); + auto const page = view().dirInsert( + keylet::ownerDir(accountID_), preauthKeylet, describeOwnerDir(accountID_)); JLOG(j_.trace()) << "Adding DepositPreauth to owner directory " << to_string(preauthKeylet.key) << ": " << (page ? "success" : "failure"); @@ -176,13 +176,13 @@ DepositPreauth::doApply() } else if (ctx_.tx.isFieldPresent(sfUnauthorize)) { - auto const preauth = keylet::depositPreauth(account_, ctx_.tx[sfUnauthorize]); + auto const preauth = keylet::depositPreauth(accountID_, ctx_.tx[sfUnauthorize]); return DepositPreauth::removeFromLedger(view(), preauth.key, j_); } else if (ctx_.tx.isFieldPresent(sfAuthorizeCredentials)) { - WritableAccountRoot wrappedOwner(account_, view()); + WritableAccountRoot wrappedOwner(accountID_, view()); if (!wrappedOwner) return tefINTERNAL; // LCOV_EXCL_LINE @@ -211,18 +211,18 @@ DepositPreauth::doApply() sortedLE.push_back(std::move(cred)); } - Keylet const preauthKey = keylet::depositPreauth(account_, sortedTX); + Keylet const preauthKey = keylet::depositPreauth(accountID_, sortedTX); auto slePreauth = std::make_shared(preauthKey); if (!slePreauth) return tefINTERNAL; // LCOV_EXCL_LINE - slePreauth->setAccountID(sfAccount, account_); + slePreauth->setAccountID(sfAccount, accountID_); slePreauth->peekFieldArray(sfAuthorizeCredentials) = std::move(sortedLE); view().insert(slePreauth); - auto const page = - view().dirInsert(keylet::ownerDir(account_), preauthKey, describeOwnerDir(account_)); + auto const page = view().dirInsert( + keylet::ownerDir(accountID_), preauthKey, describeOwnerDir(accountID_)); JLOG(j_.trace()) << "Adding DepositPreauth to owner directory " << to_string(preauthKey.key) << ": " << (page ? "success" : "failure"); @@ -238,7 +238,7 @@ DepositPreauth::doApply() else if (ctx_.tx.isFieldPresent(sfUnauthorizeCredentials)) { auto const preauthKey = keylet::depositPreauth( - account_, credentials::makeSorted(ctx_.tx.getFieldArray(sfUnauthorizeCredentials))); + accountID_, credentials::makeSorted(ctx_.tx.getFieldArray(sfUnauthorizeCredentials))); return DepositPreauth::removeFromLedger(view(), preauthKey.key, j_); } diff --git a/src/libxrpl/tx/transactors/payment/Payment.cpp b/src/libxrpl/tx/transactors/payment/Payment.cpp index c95afc33f9..475e2de78d 100644 --- a/src/libxrpl/tx/transactors/payment/Payment.cpp +++ b/src/libxrpl/tx/transactors/payment/Payment.cpp @@ -276,10 +276,9 @@ Payment::preclaim(PreclaimContext const& ctx) AccountID const dstAccountID(ctx.tx[sfDestination]); STAmount const dstAmount(ctx.tx[sfAmount]); - auto const k = keylet::account(dstAccountID); - auto const sleDst = ctx.view.read(k); + AccountRoot const dstAcct(dstAccountID, ctx.view); - if (!sleDst) + if (!dstAcct) { // Destination account does not exist. if (!dstAmount.native()) @@ -314,9 +313,7 @@ Payment::preclaim(PreclaimContext const& ctx) return tecNO_DST_INSUF_XRP; } } - else if ( - ((sleDst->getFlags() & lsfRequireDestTag) != 0u) && - !ctx.tx.isFieldPresent(sfDestinationTag)) + else if ((dstAcct->getFlags() & lsfRequireDestTag) && !ctx.tx.isFieldPresent(sfDestinationTag)) { // The tag is basically account-specific information we don't // understand, but we can require someone to fill it in. @@ -374,30 +371,29 @@ Payment::doApply() AccountID const dstAccountID(ctx_.tx.getAccountID(sfDestination)); STAmount const dstAmount(ctx_.tx.getFieldAmount(sfAmount)); bool const mptDirect = dstAmount.holds(); - STAmount const maxSourceAmount = getMaxSourceAmount(account_, dstAmount, sendMax); + STAmount const maxSourceAmount = getMaxSourceAmount(accountID_, dstAmount, sendMax); JLOG(j_.trace()) << "maxSourceAmount=" << maxSourceAmount.getFullText() << " dstAmount=" << dstAmount.getFullText(); // Open a ledger for editing. - auto const k = keylet::account(dstAccountID); - SLE::pointer sleDst = view().peek(k); + WritableAccountRoot dst(dstAccountID, view()); - if (!sleDst) + if (!dst) { // Create the account. - sleDst = std::make_shared(k); - sleDst->setAccountID(sfAccount, dstAccountID); - sleDst->setFieldU32(sfSequence, view().seq()); + dst.newSLE(); + dst->setAccountID(sfAccount, dstAccountID); + dst->setFieldU32(sfSequence, view().seq()); - view().insert(sleDst); + dst.insert(); } else { // Tell the engine that we are intending to change the destination // account. The source account gets always charged a fee so it's always // marked as modified. - view().update(sleDst); + dst.update(); } bool const ripple = (hasPaths || sendMax || !dstAmount.native()) && !mptDirect; @@ -412,8 +408,7 @@ Payment::doApply() // 1. If Account == Destination, or // 2. If Account is deposit preauthorized by destination. - if (auto err = verifyDepositPreauth( - ctx_.tx, ctx_.view(), account_, dstAccountID, sleDst, ctx_.journal); + if (auto err = verifyDepositPreauth(ctx_.tx, ctx_.view(), accountID_, dst, ctx_.journal); !isTesSuccess(err)) return err; @@ -432,7 +427,7 @@ Payment::doApply() maxSourceAmount, dstAmount, dstAccountID, - account_, + accountID_, ctx_.tx.getFieldPathSet(sfPaths), ctx_.tx[~sfDomainID], ctx_.registry.logs(), @@ -472,18 +467,17 @@ Payment::doApply() JLOG(j_.trace()) << " dstAmount=" << dstAmount.getFullText(); auto const& mptIssue = dstAmount.get(); - if (auto const ter = requireAuth(view(), mptIssue, account_); !isTesSuccess(ter)) + if (auto const ter = requireAuth(view(), mptIssue, accountID_); !isTesSuccess(ter)) return ter; if (auto const ter = requireAuth(view(), mptIssue, dstAccountID); !isTesSuccess(ter)) return ter; - if (auto const ter = canTransfer(view(), mptIssue, account_, dstAccountID); + if (auto const ter = canTransfer(view(), mptIssue, accountID_, dstAccountID); !isTesSuccess(ter)) return ter; - if (auto err = verifyDepositPreauth( - ctx_.tx, ctx_.view(), account_, dstAccountID, sleDst, ctx_.journal); + if (auto err = verifyDepositPreauth(ctx_.tx, ctx_.view(), accountID_, dst, ctx_.journal); !isTesSuccess(err)) return err; @@ -492,13 +486,13 @@ Payment::doApply() // Transfer rate Rate rate{QUALITY_ONE}; // Payment between the holders - if (account_ != issuer && dstAccountID != issuer) + if (accountID_ != issuer && dstAccountID != issuer) { // If globally/individually locked then // - can't send between holders // - holder can send back to issuer // - issuer can send to holder - if (isAnyFrozen(view(), {account_, dstAccountID}, mptIssue)) + if (isAnyFrozen(view(), {accountID_, dstAccountID}, mptIssue)) return tecLOCKED; // Get the rate for a payment between the holders. @@ -526,7 +520,7 @@ Payment::doApply() return tecPATH_PARTIAL; PaymentSandbox pv(&view()); - auto res = accountSend(pv, account_, dstAccountID, amountDeliver, ctx_.journal); + auto res = accountSend(pv, accountID_, dstAccountID, amountDeliver, ctx_.journal); if (isTesSuccess(res)) { pv.apply(ctx_.rawView()); @@ -549,13 +543,13 @@ Payment::doApply() // Direct XRP payment. - auto const sleSrc = view().peek(keylet::account(account_)); - if (!sleSrc) + WritableAccountRoot srcAcct(accountID_, view()); + if (!srcAcct) return tefINTERNAL; // LCOV_EXCL_LINE // ownerCount is the number of entries in this ledger for this // account that require a reserve. - auto const ownerCount = sleSrc->getFieldU32(sfOwnerCount); + auto const ownerCount = srcAcct->getFieldU32(sfOwnerCount); // This is the total reserve in drops. auto const reserve = view().fees().accountReserve(ownerCount); @@ -581,7 +575,7 @@ Payment::doApply() // transaction types. Note, this is not amendment-gated because all writes // to pseudo-account discriminator fields **are** amendment gated, hence the // behaviour of this check will always match the active amendments. - if (isPseudoAccount(sleDst)) + if (dst.isPseudoAccount()) return tecNO_PERMISSION; // The source account does have enough money. Make sure the @@ -608,21 +602,20 @@ Payment::doApply() // Get the base reserve. XRPAmount const dstReserve{view().fees().reserve}; - if (dstAmount > dstReserve || sleDst->getFieldAmount(sfBalance) > dstReserve) + if (dstAmount > dstReserve || dst->getFieldAmount(sfBalance) > dstReserve) { - if (auto err = verifyDepositPreauth( - ctx_.tx, ctx_.view(), account_, dstAccountID, sleDst, ctx_.journal); + if (auto err = verifyDepositPreauth(ctx_.tx, ctx_.view(), accountID_, dst, ctx_.journal); !isTesSuccess(err)) return err; } // Do the arithmetic for the transfer and make the ledger change. - sleSrc->setFieldAmount(sfBalance, sleSrc->getFieldAmount(sfBalance) - dstAmount); - sleDst->setFieldAmount(sfBalance, sleDst->getFieldAmount(sfBalance) + dstAmount); + srcAcct->setFieldAmount(sfBalance, srcAcct->getFieldAmount(sfBalance) - dstAmount); + dst->setFieldAmount(sfBalance, dst->getFieldAmount(sfBalance) + dstAmount); // Re-arm the password change fee if we can and need to. - if ((sleDst->getFlags() & lsfPasswordSpent) != 0u) - sleDst->clearFlag(lsfPasswordSpent); + if ((dst->getFlags() & lsfPasswordSpent)) + dst->clearFlag(lsfPasswordSpent); return tesSUCCESS; } diff --git a/src/libxrpl/tx/transactors/payment_channel/PaymentChannelClaim.cpp b/src/libxrpl/tx/transactors/payment_channel/PaymentChannelClaim.cpp index dccaf8f071..406260151c 100644 --- a/src/libxrpl/tx/transactors/payment_channel/PaymentChannelClaim.cpp +++ b/src/libxrpl/tx/transactors/payment_channel/PaymentChannelClaim.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -140,12 +141,12 @@ PaymentChannelClaim::doApply() return tecUNFUNDED_PAYMENT; } - auto const sled = ctx_.view().peek(keylet::account(dst)); - if (!sled) + WritableAccountRoot dstAcct(dst, ctx_.view()); + if (!dstAcct) return tecNO_DST; - if (auto err = - verifyDepositPreauth(ctx_.tx, ctx_.view(), txAccount, dst, sled, ctx_.journal); + if (auto err = verifyDepositPreauth( + ctx_.tx, ctx_.view(), txAccount, AccountRoot(dst, ctx_.view()), ctx_.journal); !isTesSuccess(err)) return err; @@ -153,8 +154,8 @@ PaymentChannelClaim::doApply() XRPAmount const reqDelta = reqBalance - chanBalance; XRPL_ASSERT( reqDelta >= beast::zero, "xrpl::PaymentChannelClaim::doApply : minimum balance delta"); - (*sled)[sfBalance] = (*sled)[sfBalance] + reqDelta; - ctx_.view().update(sled); + (*dstAcct)[sfBalance] = (*dstAcct)[sfBalance] + reqDelta; + dstAcct.update(); ctx_.view().update(slep); } diff --git a/src/libxrpl/tx/transactors/payment_channel/PaymentChannelCreate.cpp b/src/libxrpl/tx/transactors/payment_channel/PaymentChannelCreate.cpp index c29d3fe004..1846b586c2 100644 --- a/src/libxrpl/tx/transactors/payment_channel/PaymentChannelCreate.cpp +++ b/src/libxrpl/tx/transactors/payment_channel/PaymentChannelCreate.cpp @@ -58,14 +58,14 @@ TER PaymentChannelCreate::preclaim(PreclaimContext const& ctx) { auto const account = ctx.tx[sfAccount]; - auto const sle = ctx.view.read(keylet::account(account)); - if (!sle) + AccountRoot const acctSrc(account, ctx.view); + if (!acctSrc) return terNO_ACCOUNT; // Check reserve and funds availability { - auto const balance = (*sle)[sfBalance]; - auto const reserve = ctx.view.fees().accountReserve((*sle)[sfOwnerCount] + 1); + auto const balance = acctSrc->at(sfBalance); + auto const reserve = ctx.view.fees().accountReserve(acctSrc->getFieldU32(sfOwnerCount) + 1); if (balance < reserve) return tecINSUFFICIENT_RESERVE; @@ -78,11 +78,11 @@ PaymentChannelCreate::preclaim(PreclaimContext const& ctx) { // Check destination account - auto const sled = ctx.view.read(keylet::account(dst)); - if (!sled) + AccountRoot const acctDst(dst, ctx.view); + if (!acctDst) return tecNO_DST; - auto const flags = sled->getFlags(); + auto const flags = acctDst->getFlags(); // Check if they have disallowed incoming payment channels if ((flags & lsfDisallowIncomingPayChan) != 0u) @@ -97,7 +97,7 @@ PaymentChannelCreate::preclaim(PreclaimContext const& ctx) // writes to pseudo-account discriminator fields **are** amendment // gated, hence the behaviour of this check will always match the // currently active amendments. - if (isPseudoAccount(sled)) + if (acctDst.isPseudoAccount()) return tecNO_PERMISSION; } @@ -107,7 +107,7 @@ PaymentChannelCreate::preclaim(PreclaimContext const& ctx) TER PaymentChannelCreate::doApply() { - WritableAccountRoot wrappedOwner(account_, ctx_.view()); + WritableAccountRoot wrappedOwner(accountID_, ctx_.view()); if (!wrappedOwner) return tefINTERNAL; // LCOV_EXCL_LINE @@ -124,14 +124,14 @@ PaymentChannelCreate::doApply() // // Note that we we use the value from the sequence or ticket as the // payChan sequence. For more explanation see comments in SeqProxy.h. - Keylet const payChanKeylet = keylet::payChan(account_, dst, ctx_.tx.getSeqValue()); + Keylet const payChanKeylet = keylet::payChan(accountID_, dst, ctx_.tx.getSeqValue()); auto const slep = std::make_shared(payChanKeylet); // Funds held in this channel (*slep)[sfAmount] = ctx_.tx[sfAmount]; // Amount channel has already paid (*slep)[sfBalance] = ctx_.tx[sfAmount].zeroed(); - (*slep)[sfAccount] = account_; + (*slep)[sfAccount] = accountID_; (*slep)[sfDestination] = dst; (*slep)[sfSettleDelay] = ctx_.tx[sfSettleDelay]; (*slep)[sfPublicKey] = ctx_.tx[sfPublicKey]; @@ -148,7 +148,7 @@ PaymentChannelCreate::doApply() // Add PayChan to owner directory { auto const page = ctx_.view().dirInsert( - keylet::ownerDir(account_), payChanKeylet, describeOwnerDir(account_)); + keylet::ownerDir(accountID_), payChanKeylet, describeOwnerDir(accountID_)); if (!page) return tecDIR_FULL; // LCOV_EXCL_LINE (*slep)[sfOwnerNode] = *page; diff --git a/src/libxrpl/tx/transactors/payment_channel/PaymentChannelFund.cpp b/src/libxrpl/tx/transactors/payment_channel/PaymentChannelFund.cpp index 6c08cc466c..e5931eeb90 100644 --- a/src/libxrpl/tx/transactors/payment_channel/PaymentChannelFund.cpp +++ b/src/libxrpl/tx/transactors/payment_channel/PaymentChannelFund.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -60,14 +61,14 @@ PaymentChannelFund::doApply() ctx_.view().update(slep); } - auto const sle = ctx_.view().peek(keylet::account(txAccount)); - if (!sle) + WritableAccountRoot acct(txAccount, ctx_.view()); + if (!acct) return tefINTERNAL; // LCOV_EXCL_LINE { // Check reserve and funds availability - auto const balance = (*sle)[sfBalance]; - auto const reserve = ctx_.view().fees().accountReserve((*sle)[sfOwnerCount]); + auto const balance = (*acct)[sfBalance]; + auto const reserve = ctx_.view().fees().accountReserve((*acct)[sfOwnerCount]); if (balance < reserve) return tecINSUFFICIENT_RESERVE; @@ -77,7 +78,7 @@ PaymentChannelFund::doApply() } // do not allow adding funds if dst does not exist - if (AccountID const dst = (*slep)[sfDestination]; !ctx_.view().read(keylet::account(dst))) + if (AccountID const dst = (*slep)[sfDestination]; !AccountRoot(dst, ctx_.view())) { return tecNO_DST; } @@ -85,8 +86,8 @@ PaymentChannelFund::doApply() (*slep)[sfAmount] = (*slep)[sfAmount] + ctx_.tx[sfAmount]; ctx_.view().update(slep); - (*sle)[sfBalance] = (*sle)[sfBalance] - ctx_.tx[sfAmount]; - ctx_.view().update(sle); + (*acct)[sfBalance] = (*acct)[sfBalance] - ctx_.tx[sfAmount]; + acct.update(); return tesSUCCESS; } diff --git a/src/libxrpl/tx/transactors/payment_channel/PaymentChannelHelpers.cpp b/src/libxrpl/tx/transactors/payment_channel/PaymentChannelHelpers.cpp index d857225d35..b96ca78aa5 100644 --- a/src/libxrpl/tx/transactors/payment_channel/PaymentChannelHelpers.cpp +++ b/src/libxrpl/tx/transactors/payment_channel/PaymentChannelHelpers.cpp @@ -41,7 +41,6 @@ closeChannel( } // Transfer amount back to owner, decrement owner count - auto const sle = view.peek(keylet::account(src)); WritableAccountRoot wrappedOwner(src, view); if (!wrappedOwner) return tefINTERNAL; // LCOV_EXCL_LINE diff --git a/src/libxrpl/tx/transactors/permissioned_domain/PermissionedDomainDelete.cpp b/src/libxrpl/tx/transactors/permissioned_domain/PermissionedDomainDelete.cpp index d0948c5e5f..fc1e600539 100644 --- a/src/libxrpl/tx/transactors/permissioned_domain/PermissionedDomainDelete.cpp +++ b/src/libxrpl/tx/transactors/permissioned_domain/PermissionedDomainDelete.cpp @@ -44,7 +44,7 @@ PermissionedDomainDelete::doApply() auto const slePd = view().peek(keylet::permissionedDomain(ctx_.tx.at(sfDomainID))); auto const page = (*slePd)[sfOwnerNode]; - if (!view().dirRemove(keylet::ownerDir(account_), page, slePd->key(), true)) + if (!view().dirRemove(keylet::ownerDir(accountID_), page, slePd->key(), true)) { // LCOV_EXCL_START JLOG(j_.fatal()) << "Unable to delete permissioned domain directory entry."; @@ -52,7 +52,7 @@ PermissionedDomainDelete::doApply() // LCOV_EXCL_STOP } - auto wrappedOwner = WritableAccountRoot(account_, view()); + auto wrappedOwner = WritableAccountRoot(accountID_, view()); XRPL_ASSERT( wrappedOwner && wrappedOwner->getFieldU32(sfOwnerCount) > 0, "xrpl::PermissionedDomainDelete::doApply : nonzero owner count"); diff --git a/src/libxrpl/tx/transactors/permissioned_domain/PermissionedDomainSet.cpp b/src/libxrpl/tx/transactors/permissioned_domain/PermissionedDomainSet.cpp index 60a4b4c525..c2dbdbeafa 100644 --- a/src/libxrpl/tx/transactors/permissioned_domain/PermissionedDomainSet.cpp +++ b/src/libxrpl/tx/transactors/permissioned_domain/PermissionedDomainSet.cpp @@ -64,7 +64,7 @@ PermissionedDomainSet::preclaim(PreclaimContext const& ctx) TER PermissionedDomainSet::doApply() { - WritableAccountRoot wrappedOwner(account_, view()); + WritableAccountRoot wrappedOwner(accountID_, view()); if (!wrappedOwner) return tefINTERNAL; // LCOV_EXCL_LINE @@ -98,16 +98,16 @@ PermissionedDomainSet::doApply() return tecINSUFFICIENT_RESERVE; Keylet const pdKeylet = - keylet::permissionedDomain(account_, ctx_.tx.getFieldU32(sfSequence)); + keylet::permissionedDomain(accountID_, ctx_.tx.getFieldU32(sfSequence)); auto slePd = std::make_shared(pdKeylet); if (!slePd) return tefINTERNAL; // LCOV_EXCL_LINE - slePd->setAccountID(sfOwner, account_); + slePd->setAccountID(sfOwner, accountID_); slePd->setFieldU32(sfSequence, ctx_.tx.getFieldU32(sfSequence)); slePd->peekFieldArray(sfAcceptedCredentials) = std::move(sortedLE); auto const page = - view().dirInsert(keylet::ownerDir(account_), pdKeylet, describeOwnerDir(account_)); + view().dirInsert(keylet::ownerDir(accountID_), pdKeylet, describeOwnerDir(accountID_)); if (!page) return tecDIR_FULL; // LCOV_EXCL_LINE diff --git a/src/libxrpl/tx/transactors/system/Change.cpp b/src/libxrpl/tx/transactors/system/Change.cpp index b863f06cad..49f5384905 100644 --- a/src/libxrpl/tx/transactors/system/Change.cpp +++ b/src/libxrpl/tx/transactors/system/Change.cpp @@ -136,7 +136,7 @@ Change::doApply() void Change::preCompute() { - XRPL_ASSERT(account_ == beast::zero, "xrpl::Change::preCompute : zero account"); + XRPL_ASSERT(accountID_ == beast::zero, "xrpl::Change::preCompute : zero account"); } TER diff --git a/src/libxrpl/tx/transactors/system/LedgerStateFix.cpp b/src/libxrpl/tx/transactors/system/LedgerStateFix.cpp index 0ce0720ba0..4e622fe4e2 100644 --- a/src/libxrpl/tx/transactors/system/LedgerStateFix.cpp +++ b/src/libxrpl/tx/transactors/system/LedgerStateFix.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -38,7 +39,7 @@ LedgerStateFix::preclaim(PreclaimContext const& ctx) if (ctx.tx[sfLedgerFixType] == FixType::nfTokenPageLink) { AccountID const owner{ctx.tx[sfOwner]}; - if (!ctx.view.read(keylet::account(owner))) + if (!AccountRoot(owner, ctx.view)) return tecOBJECT_NOT_FOUND; return tesSUCCESS; diff --git a/src/libxrpl/tx/transactors/system/TicketCreate.cpp b/src/libxrpl/tx/transactors/system/TicketCreate.cpp index 1955a563ea..5fbbd7e755 100644 --- a/src/libxrpl/tx/transactors/system/TicketCreate.cpp +++ b/src/libxrpl/tx/transactors/system/TicketCreate.cpp @@ -30,13 +30,13 @@ TER TicketCreate::preclaim(PreclaimContext const& ctx) { auto const id = ctx.tx[sfAccount]; - auto const sleAccountRoot = ctx.view.read(keylet::account(id)); - if (!sleAccountRoot) + AccountRoot const acctRoot(id, ctx.view); + if (!acctRoot) return terNO_ACCOUNT; // Make sure the TicketCreate would not cause the account to own // too many tickets. - std::uint32_t const curTicketCount = (*sleAccountRoot)[~sfTicketCount].value_or(0u); + std::uint32_t const curTicketCount = acctRoot->at(~sfTicketCount).value_or(0u); std::uint32_t const addedTickets = ctx.tx[sfTicketCount]; std::uint32_t const consumedTickets = ctx.tx.getSeqProxy().isTicket() ? 1u : 0u; @@ -55,7 +55,7 @@ TicketCreate::preclaim(PreclaimContext const& ctx) TER TicketCreate::doApply() { - WritableAccountRoot wrappedOwner(account_, view()); + WritableAccountRoot wrappedOwner(accountID_, view()); if (!wrappedOwner) return tefINTERNAL; // LCOV_EXCL_LINE @@ -88,15 +88,15 @@ TicketCreate::doApply() for (std::uint32_t i = 0; i < ticketCount; ++i) { std::uint32_t const curTicketSeq = firstTicketSeq + i; - Keylet const ticketKeylet = keylet::ticket(account_, curTicketSeq); + Keylet const ticketKeylet = keylet::ticket(accountID_, curTicketSeq); SLE::pointer sleTicket = std::make_shared(ticketKeylet); - sleTicket->setAccountID(sfAccount, account_); + sleTicket->setAccountID(sfAccount, accountID_); sleTicket->setFieldU32(sfTicketSequence, curTicketSeq); view().insert(sleTicket); - auto const page = - view().dirInsert(keylet::ownerDir(account_), ticketKeylet, describeOwnerDir(account_)); + auto const page = view().dirInsert( + keylet::ownerDir(accountID_), ticketKeylet, describeOwnerDir(accountID_)); JLOG(j_.trace()) << "Creating ticket " << to_string(ticketKeylet.key) << ": " << (page ? "success" : "failure"); diff --git a/src/libxrpl/tx/transactors/token/Clawback.cpp b/src/libxrpl/tx/transactors/token/Clawback.cpp index 57175ba427..40243d81d8 100644 --- a/src/libxrpl/tx/transactors/token/Clawback.cpp +++ b/src/libxrpl/tx/transactors/token/Clawback.cpp @@ -163,25 +163,25 @@ Clawback::preclaim(PreclaimContext const& ctx) auto const clawAmount = ctx.tx[sfAmount]; AccountID const holder = clawAmount.holds() ? clawAmount.getIssuer() : ctx.tx[sfHolder]; - auto const sleIssuer = ctx.view.read(keylet::account(issuer)); - auto const sleHolder = ctx.view.read(keylet::account(holder)); - if (!sleIssuer || !sleHolder) + AccountRoot const acctIssuer(issuer, ctx.view); + AccountRoot const acctHolder(holder, ctx.view); + if (!acctIssuer || !acctHolder) return terNO_ACCOUNT; // Note the order of checks - when SAV is active, this check here will make // the one which follows `sleHolder->isFieldPresent(sfAMMID)` redundant. - if (ctx.view.rules().enabled(featureSingleAssetVault) && isPseudoAccount(sleHolder)) + if (ctx.view.rules().enabled(featureSingleAssetVault) && acctHolder.isPseudoAccount()) { return tecPSEUDO_ACCOUNT; } - if (sleHolder->isFieldPresent(sfAMMID)) + if (acctHolder->isFieldPresent(sfAMMID)) { return tecAMM_ACCOUNT; } return std::visit( [&](T const&) { - return preclaimHelper(ctx, *sleIssuer, issuer, holder, clawAmount); + return preclaimHelper(ctx, *acctIssuer, issuer, holder, clawAmount); }, ctx.tx[sfAmount].asset().value()); } diff --git a/src/libxrpl/tx/transactors/token/MPTokenAuthorize.cpp b/src/libxrpl/tx/transactors/token/MPTokenAuthorize.cpp index 464ede9de7..668eca293b 100644 --- a/src/libxrpl/tx/transactors/token/MPTokenAuthorize.cpp +++ b/src/libxrpl/tx/transactors/token/MPTokenAuthorize.cpp @@ -94,8 +94,7 @@ MPTokenAuthorize::preclaim(PreclaimContext const& ctx) return tesSUCCESS; } - auto const sleHolder = ctx.view.read(keylet::account(*holderID)); - if (!sleHolder) + if (AccountRoot const acctHolder(*holderID, ctx.view); !acctHolder) return tecNO_DST; auto const sleMptIssuance = ctx.view.read(keylet::mptIssuance(ctx.tx[sfMPTokenIssuanceID])); @@ -166,7 +165,7 @@ MPTokenAuthorize::doApply() ctx_.view(), preFeeBalance_, tx[sfMPTokenIssuanceID], - account_, + accountID_, ctx_.journal, tx.getFlags(), tx[~sfHolder]); diff --git a/src/libxrpl/tx/transactors/token/MPTokenIssuanceCreate.cpp b/src/libxrpl/tx/transactors/token/MPTokenIssuanceCreate.cpp index 8af43958ad..7f0054208b 100644 --- a/src/libxrpl/tx/transactors/token/MPTokenIssuanceCreate.cpp +++ b/src/libxrpl/tx/transactors/token/MPTokenIssuanceCreate.cpp @@ -141,7 +141,7 @@ MPTokenIssuanceCreate::doApply() j_, { .priorBalance = preFeeBalance_, - .account = account_, + .account = accountID_, .sequence = tx.getSeqValue(), .flags = tx.getFlags(), .maxAmount = tx[~sfMaximumAmount], diff --git a/src/libxrpl/tx/transactors/token/MPTokenIssuanceDestroy.cpp b/src/libxrpl/tx/transactors/token/MPTokenIssuanceDestroy.cpp index 0817dae920..5287c60342 100644 --- a/src/libxrpl/tx/transactors/token/MPTokenIssuanceDestroy.cpp +++ b/src/libxrpl/tx/transactors/token/MPTokenIssuanceDestroy.cpp @@ -38,15 +38,15 @@ TER MPTokenIssuanceDestroy::doApply() { auto const mpt = view().peek(keylet::mptIssuance(ctx_.tx[sfMPTokenIssuanceID])); - if (account_ != mpt->getAccountID(sfIssuer)) + if (accountID_ != mpt->getAccountID(sfIssuer)) return tecINTERNAL; // LCOV_EXCL_LINE - if (!view().dirRemove(keylet::ownerDir(account_), (*mpt)[sfOwnerNode], mpt->key(), false)) + if (!view().dirRemove(keylet::ownerDir(accountID_), (*mpt)[sfOwnerNode], mpt->key(), false)) return tefBAD_LEDGER; // LCOV_EXCL_LINE view().erase(mpt); - WritableAccountRoot acct(account_, view()); + WritableAccountRoot acct(accountID_, view()); acct.adjustOwnerCount(-1, j_); return tesSUCCESS; diff --git a/src/libxrpl/tx/transactors/token/TrustSet.cpp b/src/libxrpl/tx/transactors/token/TrustSet.cpp index 77866eff6e..8b09f11d2b 100644 --- a/src/libxrpl/tx/transactors/token/TrustSet.cpp +++ b/src/libxrpl/tx/transactors/token/TrustSet.cpp @@ -173,15 +173,15 @@ TrustSet::preclaim(PreclaimContext const& ctx) { auto const id = ctx.tx[sfAccount]; - auto const sle = ctx.view.read(keylet::account(id)); - if (!sle) + AccountRoot const acct(id, ctx.view); + if (!acct) return terNO_ACCOUNT; std::uint32_t const uTxFlags = ctx.tx.getFlags(); bool const bSetAuth = (uTxFlags & tfSetfAuth) != 0u; - if (bSetAuth && ((sle->getFieldU32(sfFlags) & lsfRequireAuth) == 0u)) + if (bSetAuth && !(acct->getFieldU32(sfFlags) & lsfRequireAuth)) { JLOG(ctx.j.trace()) << "Retry: Auth not required."; return tefNO_AUTH_REQUIRED; @@ -195,15 +195,15 @@ TrustSet::preclaim(PreclaimContext const& ctx) if (id == uDstAccountID) return temDST_IS_SRC; - // This might be nullptr - auto const sleDst = ctx.view.read(keylet::account(uDstAccountID)); + // This might not exist + AccountRoot const acctDst(uDstAccountID, ctx.view); if ((ammEnabled(ctx.view.rules()) || ctx.view.rules().enabled(featureSingleAssetVault)) && - sleDst == nullptr) + !acctDst.exists()) return tecNO_DST; // If the destination has opted to disallow incoming trustlines // then honour that flag - if ((sleDst->getFlags() & lsfDisallowIncomingTrustline) != 0u) + if (acctDst->getFlags() & lsfDisallowIncomingTrustline) { // The original implementation of featureDisallowIncoming was // too restrictive. If @@ -225,17 +225,17 @@ TrustSet::preclaim(PreclaimContext const& ctx) // enabled in the code section below, for specific cases. This block is not // amendment-gated because sleDst will not have a pseudo-account designator // field populated, unless the appropriate amendment was already enabled. - if (sleDst && isPseudoAccount(sleDst)) + if (acctDst && acctDst.isPseudoAccount()) { // If destination is AMM and the trustline doesn't exist then only allow // TrustSet if the asset is AMM LP token and AMM is not in empty state. - if (sleDst->isFieldPresent(sfAMMID)) + if (acctDst->isFieldPresent(sfAMMID)) { if (ctx.view.exists(keylet::line(id, uDstAccountID, currency))) { // pass } - else if (auto const ammSle = ctx.view.read({ltAMM, sleDst->getFieldH256(sfAMMID)})) + else if (auto const ammSle = ctx.view.read({ltAMM, acctDst->getFieldH256(sfAMMID)})) { auto const lpTokens = ammSle->getFieldAmount(sfLPTokenBalance); if (lpTokens == beast::zero) @@ -252,7 +252,7 @@ TrustSet::preclaim(PreclaimContext const& ctx) return tecINTERNAL; // LCOV_EXCL_LINE } } - else if (sleDst->isFieldPresent(sfVaultID) || sleDst->isFieldPresent(sfLoanBrokerID)) + else if (acctDst->isFieldPresent(sfVaultID) || acctDst->isFieldPresent(sfLoanBrokerID)) { if (!ctx.view.exists(keylet::line(id, uDstAccountID, currency))) return tecNO_PERMISSION; @@ -267,9 +267,9 @@ TrustSet::preclaim(PreclaimContext const& ctx) // Checking all freeze/deep freeze flag invariants. if (ctx.view.rules().enabled(featureDeepFreeze)) { - bool const bNoFreeze = sle->isFlag(lsfNoFreeze); - bool const bSetFreeze = (uTxFlags & tfSetFreeze) != 0u; - bool const bSetDeepFreeze = (uTxFlags & tfSetDeepFreeze) != 0u; + bool const bNoFreeze = acct->isFlag(lsfNoFreeze); + bool const bSetFreeze = (uTxFlags & tfSetFreeze); + bool const bSetDeepFreeze = (uTxFlags & tfSetDeepFreeze); if (bNoFreeze && (bSetFreeze || bSetDeepFreeze)) { @@ -322,9 +322,9 @@ TrustSet::doApply() AccountID uDstAccountID(saLimitAmount.getIssuer()); // true, if current is high account. - bool const bHigh = account_ > uDstAccountID; + bool const bHigh = accountID_ > uDstAccountID; - WritableAccountRoot wrappedAccount(account_, view()); + WritableAccountRoot wrappedAccount(accountID_, view()); if (!wrappedAccount) return tefINTERNAL; // LCOV_EXCL_LINE @@ -378,9 +378,9 @@ TrustSet::doApply() } STAmount saLimitAllow = saLimitAmount; - saLimitAllow.setIssuer(account_); + saLimitAllow.setIssuer(accountID_); - SLE::pointer sleRippleState = view().peek(keylet::line(account_, uDstAccountID, currency)); + SLE::pointer sleRippleState = view().peek(keylet::line(accountID_, uDstAccountID, currency)); if (sleRippleState) { @@ -392,8 +392,8 @@ TrustSet::doApply() std::uint32_t uLowQualityOut = 0; std::uint32_t uHighQualityIn = 0; std::uint32_t uHighQualityOut = 0; - auto const& uLowAccountID = !bHigh ? account_ : uDstAccountID; - auto const& uHighAccountID = bHigh ? account_ : uDstAccountID; + auto const& uLowAccountID = !bHigh ? accountID_ : uDstAccountID; + auto const& uHighAccountID = bHigh ? accountID_ : uDstAccountID; auto lowAcct = !bHigh ? wrappedAccount : wrappedDst; auto highAcct = bHigh ? wrappedAccount : wrappedDst; @@ -628,7 +628,7 @@ TrustSet::doApply() // Zero balance in currency. STAmount saBalance(Issue{currency, noAccount()}); - auto const k = keylet::line(account_, uDstAccountID, currency); + auto const k = keylet::line(accountID_, uDstAccountID, currency); JLOG(j_.trace()) << "doTrustSet: Creating ripple line: " << to_string(k.key); @@ -636,7 +636,7 @@ TrustSet::doApply() terResult = trustCreate( view(), bHigh, - account_, + accountID_, uDstAccountID, k.key, wrappedAccount, diff --git a/src/libxrpl/tx/transactors/vault/VaultClawback.cpp b/src/libxrpl/tx/transactors/vault/VaultClawback.cpp index a650aed310..851e084501 100644 --- a/src/libxrpl/tx/transactors/vault/VaultClawback.cpp +++ b/src/libxrpl/tx/transactors/vault/VaultClawback.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -180,8 +181,8 @@ VaultClawback::preclaim(PreclaimContext const& ctx) } else if constexpr (std::is_same_v) { - auto const issuerSle = ctx.view.read(keylet::account(account)); - if (!issuerSle) + AccountRoot const acctIssuer(account, ctx.view); + if (!acctIssuer) { // LCOV_EXCL_START JLOG(ctx.j.error()) << "VaultClawback: missing submitter account."; @@ -189,7 +190,7 @@ VaultClawback::preclaim(PreclaimContext const& ctx) // LCOV_EXCL_STOP } - std::uint32_t const issuerFlags = issuerSle->getFieldU32(sfFlags); + std::uint32_t const issuerFlags = acctIssuer->getFieldU32(sfFlags); if (!(issuerFlags & lsfAllowTrustLineClawback) || (issuerFlags & lsfNoFreeze)) { JLOG(ctx.j.debug()) << "VaultClawback: cannot clawback " @@ -324,7 +325,7 @@ VaultClawback::doApply() MPTIssue const share{mptIssuanceID}; Asset const vaultAsset = vault->at(sfAsset); - STAmount const amount = clawbackAmount(vault, tx[~sfAmount], account_); + STAmount const amount = clawbackAmount(vault, tx[~sfAmount], accountID_); auto assetsAvailable = vault->at(sfAssetsAvailable); auto assetsTotal = vault->at(sfAssetsTotal); @@ -339,7 +340,7 @@ VaultClawback::doApply() STAmount assetsRecovered = {vault->at(sfAsset)}; // The Owner is burning shares - if (account_ == vault->at(sfOwner) && amount.asset() == share) + if (accountID_ == vault->at(sfOwner) && amount.asset() == share) { sharesDestroyed = accountHolds( view(), @@ -406,7 +407,7 @@ VaultClawback::doApply() { // Transfer assets from vault to issuer. if (auto const ter = accountSend( - view(), vaultAccount, account_, assetsRecovered, j_, WaiveTransferFee::Yes); + view(), vaultAccount, accountID_, assetsRecovered, j_, WaiveTransferFee::Yes); !isTesSuccess(ter)) return ter; diff --git a/src/libxrpl/tx/transactors/vault/VaultCreate.cpp b/src/libxrpl/tx/transactors/vault/VaultCreate.cpp index 76971bac8f..ddb351a655 100644 --- a/src/libxrpl/tx/transactors/vault/VaultCreate.cpp +++ b/src/libxrpl/tx/transactors/vault/VaultCreate.cpp @@ -133,13 +133,13 @@ VaultCreate::doApply() auto const& tx = ctx_.tx; auto const sequence = tx.getSeqValue(); - WritableAccountRoot owner(account_, view()); + WritableAccountRoot owner(accountID_, view()); if (!owner) return tefINTERNAL; // LCOV_EXCL_LINE - auto vault = std::make_shared(keylet::vault(account_, sequence)); + auto vault = std::make_shared(keylet::vault(accountID_, sequence)); - if (auto ter = dirLink(view(), account_, vault)) + if (auto ter = dirLink(view(), accountID_, vault)) return ter; // We will create Vault and PseudoAccount, hence increase OwnerCount by 2 owner.adjustOwnerCount(2, j_); @@ -191,7 +191,7 @@ VaultCreate::doApply() vault->setFieldIssue(sfAsset, STIssue{sfAsset, asset}); vault->at(sfFlags) = txFlags & tfVaultPrivate; vault->at(sfSequence) = sequence; - vault->at(sfOwner) = account_; + vault->at(sfOwner) = accountID_; vault->at(sfAccount) = pseudoId; vault->at(sfAssetsTotal) = Number(0); vault->at(sfAssetsAvailable) = Number(0); @@ -217,7 +217,7 @@ VaultCreate::doApply() // Explicitly create MPToken for the vault owner if (auto const err = - authorizeMPToken(view(), preFeeBalance_, mptIssuanceID, account_, ctx_.journal); + authorizeMPToken(view(), preFeeBalance_, mptIssuanceID, accountID_, ctx_.journal); !isTesSuccess(err)) return err; @@ -225,7 +225,7 @@ VaultCreate::doApply() if ((txFlags & tfVaultPrivate) != 0u) { if (auto const err = authorizeMPToken( - view(), preFeeBalance_, mptIssuanceID, pseudoId, ctx_.journal, {}, account_); + view(), preFeeBalance_, mptIssuanceID, pseudoId, ctx_.journal, {}, accountID_); !isTesSuccess(err)) return err; } diff --git a/src/libxrpl/tx/transactors/vault/VaultDelete.cpp b/src/libxrpl/tx/transactors/vault/VaultDelete.cpp index db108e1f91..74312e0bea 100644 --- a/src/libxrpl/tx/transactors/vault/VaultDelete.cpp +++ b/src/libxrpl/tx/transactors/vault/VaultDelete.cpp @@ -113,16 +113,16 @@ VaultDelete::doApply() } // Try to remove MPToken for vault shares for the vault owner if it exists. - if (auto const mptoken = view().peek(keylet::mptoken(shareMPTID, account_))) + if (auto const mptoken = view().peek(keylet::mptoken(shareMPTID, accountID_))) { - if (auto const ter = removeEmptyHolding(view(), account_, MPTIssue(shareMPTID), j_); + if (auto const ter = removeEmptyHolding(view(), accountID_, MPTIssue(shareMPTID), j_); !isTesSuccess(ter)) { // LCOV_EXCL_START JLOG(j_.error()) // << "VaultDelete: failed to remove vault owner's MPToken" - << " MPTID=" << to_string(shareMPTID) // - << " account=" << toBase58(account_) // + << " MPTID=" << to_string(shareMPTID) // + << " account=" << toBase58(accountID_) // << " with result: " << transToken(ter); return ter; // LCOV_EXCL_STOP @@ -145,20 +145,20 @@ VaultDelete::doApply() return tecHAS_OBLIGATIONS; // LCOV_EXCL_LINE // Destroy the pseudo-account. - auto vaultPseudoSLE = view().peek(keylet::account(pseudoID)); - if (!vaultPseudoSLE || vaultPseudoSLE->at(~sfVaultID) != vault->key()) + WritableAccountRoot vaultPseudo(pseudoID, view()); + if (!vaultPseudo || vaultPseudo->at(~sfVaultID) != vault->key()) return tefBAD_LEDGER; // LCOV_EXCL_LINE // Making the payment and removing the empty holding should have deleted any // obligations associated with the vault or vault pseudo-account. - if (*vaultPseudoSLE->at(sfBalance)) + if (*vaultPseudo->at(sfBalance)) { // LCOV_EXCL_START JLOG(j_.error()) << "VaultDelete: pseudo-account has a balance"; return tecHAS_OBLIGATIONS; // LCOV_EXCL_STOP } - if (vaultPseudoSLE->at(sfOwnerCount) != 0) + if (vaultPseudo->at(sfOwnerCount) != 0) { // LCOV_EXCL_START JLOG(j_.error()) << "VaultDelete: pseudo-account still owns objects"; @@ -173,7 +173,7 @@ VaultDelete::doApply() // LCOV_EXCL_STOP } - view().erase(vaultPseudoSLE); + vaultPseudo.erase(); // Remove the vault from its owner's directory. auto const ownerID = vault->at(sfOwner); diff --git a/src/libxrpl/tx/transactors/vault/VaultDeposit.cpp b/src/libxrpl/tx/transactors/vault/VaultDeposit.cpp index 04b249d211..b466a659c9 100644 --- a/src/libxrpl/tx/transactors/vault/VaultDeposit.cpp +++ b/src/libxrpl/tx/transactors/vault/VaultDeposit.cpp @@ -148,20 +148,20 @@ VaultDeposit::doApply() auto const& vaultAccount = vault->at(sfAccount); // Note, vault owner is always authorized - if (vault->isFlag(lsfVaultPrivate) && account_ != vault->at(sfOwner)) + if (vault->isFlag(lsfVaultPrivate) && accountID_ != vault->at(sfOwner)) { if (auto const err = enforceMPTokenAuthorization( - ctx_.view(), mptIssuanceID, account_, preFeeBalance_, j_); + ctx_.view(), mptIssuanceID, accountID_, preFeeBalance_, j_); !isTesSuccess(err)) return err; } - else // !vault->isFlag(lsfVaultPrivate) || account_ == vault->at(sfOwner) + else // !vault->isFlag(lsfVaultPrivate) || accountID_ == vault->at(sfOwner) { // No authorization needed, but must ensure there is MPToken - if (!view().exists(keylet::mptoken(mptIssuanceID, account_))) + if (!view().exists(keylet::mptoken(mptIssuanceID, accountID_))) { if (auto const err = authorizeMPToken( - view(), preFeeBalance_, mptIssuanceID->value(), account_, ctx_.journal); + view(), preFeeBalance_, mptIssuanceID->value(), accountID_, ctx_.journal); !isTesSuccess(err)) return err; } @@ -171,15 +171,15 @@ VaultDeposit::doApply() { // This follows from the reverse of the outer enclosing if condition XRPL_ASSERT( - account_ == vault->at(sfOwner), "xrpl::VaultDeposit::doApply : account is owner"); + accountID_ == vault->at(sfOwner), "xrpl::VaultDeposit::doApply : account is owner"); if (auto const err = authorizeMPToken( view(), preFeeBalance_, // priorBalance mptIssuanceID->value(), // mptIssuanceID sleIssuance->at(sfIssuer), // account ctx_.journal, - {}, // flags - account_ // holderID + {}, // flags + accountID_ // holderID ); !isTesSuccess(err)) return err; @@ -239,15 +239,15 @@ VaultDeposit::doApply() return tecLIMIT_EXCEEDED; // Transfer assets from depositor to vault. - if (auto const ter = - accountSend(view(), account_, vaultAccount, assetsDeposited, j_, WaiveTransferFee::Yes); + if (auto const ter = accountSend( + view(), accountID_, vaultAccount, assetsDeposited, j_, WaiveTransferFee::Yes); !isTesSuccess(ter)) return ter; // Sanity check if (accountHolds( view(), - account_, + accountID_, assetsDeposited.asset(), FreezeHandling::fhIGNORE_FREEZE, AuthHandling::ahIGNORE_AUTH, @@ -261,7 +261,7 @@ VaultDeposit::doApply() // Transfer shares from vault to depositor. if (auto const ter = - accountSend(view(), vaultAccount, account_, sharesCreated, j_, WaiveTransferFee::Yes); + accountSend(view(), vaultAccount, accountID_, sharesCreated, j_, WaiveTransferFee::Yes); !isTesSuccess(ter)) return ter; diff --git a/src/libxrpl/tx/transactors/vault/VaultWithdraw.cpp b/src/libxrpl/tx/transactors/vault/VaultWithdraw.cpp index e4c671b462..8466d3af11 100644 --- a/src/libxrpl/tx/transactors/vault/VaultWithdraw.cpp +++ b/src/libxrpl/tx/transactors/vault/VaultWithdraw.cpp @@ -165,7 +165,7 @@ VaultWithdraw::doApply() if (accountHolds( view(), - account_, + accountID_, share, FreezeHandling::fhZERO_IF_FROZEN, AuthHandling::ahIGNORE_AUTH, @@ -197,23 +197,23 @@ VaultWithdraw::doApply() auto const& vaultAccount = vault->at(sfAccount); // Transfer shares from depositor to vault. - if (auto const ter = - accountSend(view(), account_, vaultAccount, sharesRedeemed, j_, WaiveTransferFee::Yes); + if (auto const ter = accountSend( + view(), accountID_, vaultAccount, sharesRedeemed, j_, WaiveTransferFee::Yes); !isTesSuccess(ter)) return ter; // Try to remove MPToken for shares, if the account balance is zero. Vault // pseudo-account will never set lsfMPTAuthorized, so we ignore flags. // Keep MPToken if holder is the vault owner. - if (account_ != vault->at(sfOwner)) + if (accountID_ != vault->at(sfOwner)) { - if (auto const ter = removeEmptyHolding(view(), account_, sharesRedeemed.asset(), j_); + if (auto const ter = removeEmptyHolding(view(), accountID_, sharesRedeemed.asset(), j_); isTesSuccess(ter)) { JLOG(j_.debug()) // << "VaultWithdraw: removed empty MPToken for vault shares" << " MPTID=" << to_string(mptIssuanceID) // - << " account=" << toBase58(account_); + << " account=" << toBase58(accountID_); } else if (ter != tecHAS_OBLIGATIONS) { @@ -221,7 +221,7 @@ VaultWithdraw::doApply() JLOG(j_.error()) // << "VaultWithdraw: failed to remove MPToken for vault shares" << " MPTID=" << to_string(mptIssuanceID) // - << " account=" << toBase58(account_) // + << " account=" << toBase58(accountID_) // << " with result: " << transToken(ter); return ter; // LCOV_EXCL_STOP @@ -229,12 +229,12 @@ VaultWithdraw::doApply() // else quietly ignore, account balance is not zero } - auto const dstAcct = ctx_.tx[~sfDestination].value_or(account_); + auto const dstAcct = ctx_.tx[~sfDestination].value_or(accountID_); associateAsset(*vault, vaultAsset); return doWithdraw( - view(), ctx_.tx, account_, dstAcct, vaultAccount, preFeeBalance_, assetsWithdrawn, j_); + view(), ctx_.tx, accountID_, dstAcct, vaultAccount, preFeeBalance_, assetsWithdrawn, j_); } } // namespace xrpl diff --git a/src/xrpld/app/ledger/detail/LocalTxs.cpp b/src/xrpld/app/ledger/detail/LocalTxs.cpp index 8eb821a6c9..4d071763a7 100644 --- a/src/xrpld/app/ledger/detail/LocalTxs.cpp +++ b/src/xrpld/app/ledger/detail/LocalTxs.cpp @@ -1,6 +1,7 @@ #include #include +#include #include /* @@ -130,12 +131,12 @@ public: return true; AccountID const acctID = txn.getAccount(); - auto const sleAcct = view.read(keylet::account(acctID)); + AccountRoot const acctRoot(acctID, view); - if (!sleAcct) + if (!acctRoot) return false; - SeqProxy const acctSeq = SeqProxy::sequence(sleAcct->getFieldU32(sfSequence)); + SeqProxy const acctSeq = SeqProxy::sequence(acctRoot->getFieldU32(sfSequence)); SeqProxy const seqProx = txn.getSeqProxy(); if (seqProx.isSeq()) diff --git a/src/xrpld/app/misc/detail/TxQ.cpp b/src/xrpld/app/misc/detail/TxQ.cpp index 78e8ccdba5..9b3f284649 100644 --- a/src/xrpld/app/misc/detail/TxQ.cpp +++ b/src/xrpld/app/misc/detail/TxQ.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -1606,13 +1607,13 @@ TxQ::tryDirectApply( beast::Journal j) { auto const account = (*tx)[sfAccount]; - auto const sleAccount = view.read(keylet::account(account)); + AccountRoot const acctRoot(account, view); // Don't attempt to direct apply if the account is not in the ledger. - if (!sleAccount) + if (!acctRoot) return {}; - SeqProxy const acctSeqProx = SeqProxy::sequence((*sleAccount)[sfSequence]); + SeqProxy const acctSeqProx = SeqProxy::sequence(acctRoot->at(sfSequence)); SeqProxy const txSeqProx = tx->getSeqProxy(); // Can only directly apply if the transaction sequence matches the account @@ -1721,10 +1722,10 @@ TxQ::getTxRequiredFeeAndSeq(OpenView const& view, std::shared_ptr co auto const baseFee = calculateBaseFee(view, *tx); auto const fee = FeeMetrics::scaleFeeLevel(snapshot, view); - auto const sle = view.read(keylet::account(account)); + AccountRoot const acctInfo(account, view); - std::uint32_t const accountSeq = sle ? (*sle)[sfSequence] : 0; - std::uint32_t const availableSeq = nextQueuableSeqImpl(sle, lock).value(); + std::uint32_t const accountSeq = acctInfo ? acctInfo->at(sfSequence) : 0; + std::uint32_t const availableSeq = nextQueuableSeqImpl(acctInfo.sle(), lock).value(); return { mulDiv(fee, baseFee, baseLevel) .value_or(XRPAmount(std::numeric_limits::max())), diff --git a/src/xrpld/app/paths/PathRequest.cpp b/src/xrpld/app/paths/PathRequest.cpp index 0e895e66d4..d77aa2790a 100644 --- a/src/xrpld/app/paths/PathRequest.cpp +++ b/src/xrpld/app/paths/PathRequest.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -168,11 +169,11 @@ PathRequest::isValid(std::shared_ptr const& crCache) return false; } - auto const sleDest = lrLedger->read(keylet::account(*raDstAccount)); + AccountRoot const acctDest(*raDstAccount, *lrLedger); Json::Value& jvDestCur = (jvStatus[jss::destination_currencies] = Json::arrayValue); - if (!sleDest) + if (!acctDest) { jvDestCur.append(Json::Value(systemCurrencyCode())); if (!saDstAmount.native()) @@ -191,13 +192,13 @@ PathRequest::isValid(std::shared_ptr const& crCache) } else { - bool const disallowXRP((sleDest->getFlags() & lsfDisallowXRP) != 0u); + bool const disallowXRP(acctDest->getFlags() & lsfDisallowXRP); auto usDestCurrID = accountDestCurrencies(*raDstAccount, crCache, !disallowXRP); for (auto const& currency : usDestCurrID) jvDestCur.append(to_string(currency)); - jvStatus[jss::destination_tag] = (sleDest->getFlags() & lsfRequireDestTag); + jvStatus[jss::destination_tag] = (acctDest->getFlags() & lsfRequireDestTag); } jvStatus[jss::ledger_hash] = to_string(lrLedger->header().hash); diff --git a/src/xrpld/app/paths/Pathfinder.cpp b/src/xrpld/app/paths/Pathfinder.cpp index 10d69fc040..8eacd3229c 100644 --- a/src/xrpld/app/paths/Pathfinder.cpp +++ b/src/xrpld/app/paths/Pathfinder.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -699,12 +700,12 @@ Pathfinder::getPathsOut( if (!inserted) return it->second; - auto sleAccount = mLedger->read(keylet::account(account)); + AccountRoot const acctRoot(account, *mLedger); - if (!sleAccount) + if (!acctRoot) return 0; - int aFlags = sleAccount->getFieldU32(sfFlags); + int aFlags = acctRoot->getFieldU32(sfFlags); bool const bAuthRequired = (aFlags & lsfRequireAuth) != 0; bool const bFrozen = ((aFlags & lsfGlobalFreeze) != 0); @@ -926,11 +927,11 @@ Pathfinder::addLink( else { // search for accounts to add - auto const sleEnd = mLedger->read(keylet::account(uEndAccount)); + AccountRoot const acctEnd(uEndAccount, *mLedger); - if (sleEnd) + if (acctEnd) { - bool const bRequireAuth((sleEnd->getFieldU32(sfFlags) & lsfRequireAuth) != 0u); + bool const bRequireAuth(acctEnd->getFieldU32(sfFlags) & lsfRequireAuth); bool const bIsEndCurrency(uEndCurrency == mDstAmount.getCurrency()); bool const bIsNoRippleOut(isNoRippleOut(currentPath)); bool const bDestOnly((addFlags & afAC_LAST) != 0u); diff --git a/src/xrpld/app/paths/detail/BookStep.cpp b/src/xrpld/app/paths/detail/BookStep.cpp index a6b3e0e61a..1a6252bf3e 100644 --- a/src/xrpld/app/paths/detail/BookStep.cpp +++ b/src/xrpld/app/paths/detail/BookStep.cpp @@ -700,8 +700,8 @@ BookStep::forEachOffer( if (!isXRP(offer.issueIn().currency) && offer.owner() != offer.issueIn().account) { auto const& issuerID = offer.issueIn().account; - auto const issuer = afView.read(keylet::account(issuerID)); - if (issuer && ((*issuer)[sfFlags] & lsfRequireAuth)) + AccountRoot const acctIssuer(issuerID, afView); + if (acctIssuer && (acctIssuer->getFlags() & lsfRequireAuth)) { // Issuer requires authorization. See if offer owner has that. auto const& ownerID = offer.owner(); @@ -1277,7 +1277,7 @@ BookStep::check(StrandContext const& ctx) const } auto issuerExists = [](ReadView const& view, Issue const& iss) -> bool { - return isXRP(iss.account) || view.read(keylet::account(iss.account)); + return isXRP(iss.account) || AccountRoot(iss.account, view); }; if (!issuerExists(ctx.view, book_.in) || !issuerExists(ctx.view, book_.out)) diff --git a/src/xrpld/app/paths/detail/DirectStep.cpp b/src/xrpld/app/paths/detail/DirectStep.cpp index 5d3f4a3b83..bfee6e38b3 100644 --- a/src/xrpld/app/paths/detail/DirectStep.cpp +++ b/src/xrpld/app/paths/detail/DirectStep.cpp @@ -814,8 +814,8 @@ DirectStepI::check(StrandContext const& ctx) const return temBAD_PATH; } - auto const sleSrc = ctx.view.read(keylet::account(src_)); - if (!sleSrc) + AccountRoot const acctSrc(src_, ctx.view); + if (!acctSrc) { JLOG(j_.warn()) << "DirectStepI: can't receive IOUs from non-existent issuer: " << src_; return terNO_ACCOUNT; @@ -874,7 +874,7 @@ DirectStepI::check(StrandContext const& ctx) const } } - return static_cast(this)->check(ctx, sleSrc); + return static_cast(this)->check(ctx, acctSrc.sle()); } //------------------------------------------------------------------------------ diff --git a/src/xrpld/app/paths/detail/StepChecks.h b/src/xrpld/app/paths/detail/StepChecks.h index c866705a4c..631f93c17e 100644 --- a/src/xrpld/app/paths/detail/StepChecks.h +++ b/src/xrpld/app/paths/detail/StepChecks.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -19,9 +20,10 @@ checkFreeze( XRPL_ASSERT(src != dst, "xrpl::checkFreeze : unequal input accounts"); // check freeze - if (auto sle = view.read(keylet::account(dst))) + AccountRoot const acctDst(dst, view); + if (acctDst) { - if (sle->isFlag(lsfGlobalFreeze)) + if (acctDst->isFlag(lsfGlobalFreeze)) { return terNO_LINE; } @@ -43,10 +45,9 @@ checkFreeze( if (view.rules().enabled(fixFrozenLPTokenTransfer)) { - if (auto const sleDst = view.read(keylet::account(dst)); - sleDst && sleDst->isFieldPresent(sfAMMID)) + if (AccountRoot const acctDst2(dst, view); acctDst2 && acctDst2->isFieldPresent(sfAMMID)) { - auto const sleAmm = view.read(keylet::amm((*sleDst)[sfAMMID])); + auto const sleAmm = view.read(keylet::amm(acctDst2->at(sfAMMID))); if (!sleAmm) return tecINTERNAL; // LCOV_EXCL_LINE diff --git a/src/xrpld/app/paths/detail/XRPEndpointStep.cpp b/src/xrpld/app/paths/detail/XRPEndpointStep.cpp index 1077b221e3..e3693e6206 100644 --- a/src/xrpld/app/paths/detail/XRPEndpointStep.cpp +++ b/src/xrpld/app/paths/detail/XRPEndpointStep.cpp @@ -317,8 +317,8 @@ XRPEndpointStep::check(StrandContext const& ctx) const return temBAD_PATH; } - auto sleAcc = ctx.view.read(keylet::account(acc_)); - if (!sleAcc) + AccountRoot const acctRoot(acc_, ctx.view); + if (!acctRoot) { JLOG(j_.warn()) << "XRPEndpointStep: can't send or receive XRP from " "non-existent account: " diff --git a/src/xrpld/rpc/detail/TransactionSign.cpp b/src/xrpld/rpc/detail/TransactionSign.cpp index 73385f62ef..ac601e7ffb 100644 --- a/src/xrpld/rpc/detail/TransactionSign.cpp +++ b/src/xrpld/rpc/detail/TransactionSign.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -126,17 +127,14 @@ public: //------------------------------------------------------------------------------ static error_code_i -acctMatchesPubKey( - std::shared_ptr accountState, - AccountID const& accountID, - PublicKey const& publicKey) +acctMatchesPubKey(AccountRoot const& account, PublicKey const& publicKey) { auto const publicKeyAcctID = calcAccountID(publicKey); - bool const isMasterKey = publicKeyAcctID == accountID; + bool const isMasterKey = publicKeyAcctID == account.id(); // If we can't get the accountRoot, but the accountIDs match, that's // good enough. - if (!accountState) + if (!account) { if (isMasterKey) return rpcSUCCESS; @@ -144,16 +142,16 @@ acctMatchesPubKey( } // If we *can* get to the accountRoot, check for MASTER_DISABLED. - auto const& sle = *accountState; if (isMasterKey) { - if (sle.isFlag(lsfDisableMaster)) + if (account->isFlag(lsfDisableMaster)) return rpcMASTER_DISABLED; return rpcSUCCESS; } // The last gasp is that we have public Regular key. - if ((sle.isFieldPresent(sfRegularKey)) && (publicKeyAcctID == sle.getAccountID(sfRegularKey))) + if ((account->isFieldPresent(sfRegularKey)) && + (publicKeyAcctID == account->getAccountID(sfRegularKey))) { return rpcSUCCESS; } @@ -459,11 +457,11 @@ transactionPreProcessImpl( if (!verify && !tx_json.isMember(jss::Sequence)) return RPC::missing_field_error("tx_json.Sequence"); - std::shared_ptr sle; + std::optional acctSrc; if (verify) - sle = app.openLedger().current()->read(keylet::account(srcAddressID)); + acctSrc.emplace(srcAddressID, *app.openLedger().current()); - if (verify && !sle) + if (verify && !acctSrc.value() && acctSrc->exists()) { // If not offline and did not find account, error. JLOG(j.debug()) << "transactionSign: Failed to find source account " @@ -477,14 +475,15 @@ transactionPreProcessImpl( if (!tx_json.isMember(jss::Sequence)) { bool const hasTicketSeq = tx_json.isMember(sfTicketSequence.jsonName); - if (!hasTicketSeq && !sle) + if (!hasTicketSeq && (!acctSrc || !acctSrc->exists())) { JLOG(j.debug()) << "transactionSign: Failed to find source account " << "in current ledger: " << toBase58(srcAddressID); return rpcError(rpcSRC_ACT_NOT_FOUND); } - tx_json[jss::Sequence] = hasTicketSeq ? 0 : app.getTxQ().nextQueuableSeq(sle).value(); + tx_json[jss::Sequence] = + hasTicketSeq ? 0 : app.getTxQ().nextQueuableSeq(acctSrc->sle()).value(); } if (!tx_json.isMember(jss::NetworkID)) @@ -534,7 +533,7 @@ transactionPreProcessImpl( if (verify) { - if (!sle) + if (!acctSrc || !acctSrc->exists()) { // XXX Ignore transactions for accounts not created. return rpcError(rpcSRC_ACT_NOT_FOUND); @@ -564,19 +563,18 @@ transactionPreProcessImpl( } auto delegatedAddressID = *ptrDelegatedAddressID; - auto delegatedSle = - app.openLedger().current()->read(keylet::account(delegatedAddressID)); - if (!delegatedSle) + AccountRoot const acctDelegated(delegatedAddressID, *app.openLedger().current()); + if (!acctDelegated) return rpcError(rpcDELEGATE_ACT_NOT_FOUND); - auto const err = acctMatchesPubKey(delegatedSle, delegatedAddressID, pk); + auto const err = acctMatchesPubKey(acctDelegated, pk); if (err != rpcSUCCESS) return rpcError(err); } else { - auto const err = acctMatchesPubKey(sle, srcAddressID, pk); + auto const err = acctMatchesPubKey(*acctSrc, pk); if (err != rpcSUCCESS) return rpcError(err); @@ -1161,10 +1159,9 @@ transactionSignFor( signForParams.validMultiSign(), "xrpl::RPC::transactionSignFor : valid multi-signature"); { - std::shared_ptr account_state = ledger->read(keylet::account(*signerAccountID)); + AccountRoot const acctSigner(*signerAccountID, *ledger); // Make sure the account and secret belong together. - auto const err = - acctMatchesPubKey(account_state, *signerAccountID, signForParams.getPublicKey()); + auto const err = acctMatchesPubKey(acctSigner, signForParams.getPublicKey()); if (err != rpcSUCCESS) return rpcError(err); @@ -1246,9 +1243,9 @@ transactionSubmitMultiSigned( if (RPC::contains_error(txJsonResult)) return std::move(txJsonResult); - std::shared_ptr sle = ledger->read(keylet::account(srcAddressID)); + AccountRoot const acctSrcMulti(srcAddressID, *ledger); - if (!sle) + if (!acctSrcMulti) { // If did not find account, error. JLOG(j.debug()) << "transactionSubmitMultiSigned: Failed to find source account " diff --git a/src/xrpld/rpc/handlers/AMMInfo.cpp b/src/xrpld/rpc/handlers/AMMInfo.cpp index 42e44f004d..8cfbfccbb5 100644 --- a/src/xrpld/rpc/handlers/AMMInfo.cpp +++ b/src/xrpld/rpc/handlers/AMMInfo.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -101,10 +102,10 @@ doAMMInfo(RPC::JsonContext& context) auto const id = parseBase58((params[jss::amm_account].asString())); if (!id) return Unexpected(rpcACT_MALFORMED); - auto const sle = ledger->read(keylet::account(*id)); - if (!sle) + AccountRoot const acctAmm(*id, *ledger); + if (!acctAmm) return Unexpected(rpcACT_MALFORMED); - ammID = sle->getFieldH256(sfAMMID); + ammID = acctAmm->getFieldH256(sfAMMID); if (ammID->isZero()) return Unexpected(rpcACT_NOT_FOUND); } @@ -112,7 +113,7 @@ doAMMInfo(RPC::JsonContext& context) if (params.isMember(jss::account)) { accountID = parseBase58(params[jss::account].asString()); - if (!accountID || !ledger->read(keylet::account(*accountID))) + if (!accountID || !AccountRoot(*accountID, *ledger)) return Unexpected(rpcACT_MALFORMED); } diff --git a/src/xrpld/rpc/handlers/AccountInfo.cpp b/src/xrpld/rpc/handlers/AccountInfo.cpp index 55f05ddcab..e197ec9483 100644 --- a/src/xrpld/rpc/handlers/AccountInfo.cpp +++ b/src/xrpld/rpc/handlers/AccountInfo.cpp @@ -29,26 +29,19 @@ namespace xrpl { * If the entry is not an account root, sets the 'Invalid' field to true. */ void -injectSLE(Json::Value& jv, SLE const& sle) +injectSLE(Json::Value& jv, AccountRoot const& account) { - jv = sle.getJson(JsonOptions::none); - if (sle.getType() == ltACCOUNT_ROOT) + jv = account->getJson(JsonOptions::none); + if (account->isFieldPresent(sfEmailHash)) { - if (sle.isFieldPresent(sfEmailHash)) - { - auto const& hash = sle.getFieldH128(sfEmailHash); - Blob const b(hash.begin(), hash.end()); - std::string md5 = strHex(makeSlice(b)); - boost::to_lower(md5); - // VFALCO TODO Give a name and move this constant - // to a more visible location. Also - // shouldn't this be https? - jv[jss::urlgravatar] = str(boost::format("http://www.gravatar.com/avatar/%s") % md5); - } - } - else - { - jv[jss::Invalid] = true; + auto const& hash = account->getFieldH128(sfEmailHash); + Blob const b(hash.begin(), hash.end()); + std::string md5 = strHex(makeSlice(b)); + boost::to_lower(md5); + // VFALCO TODO Give a name and move this constant + // to a more visible location. Also + // shouldn't this be https? + jv[jss::urlgravatar] = str(boost::format("http://www.gravatar.com/avatar/%s") % md5); } } @@ -128,8 +121,8 @@ doAccountInfo(RPC::JsonContext& context) static constexpr std::pair allowTrustLineLockingFlag{ "allowTrustLineLocking", lsfAllowTrustLineLocking}; - auto const sleAccepted = ledger->read(keylet::account(accountID)); - if (sleAccepted) + AccountRoot const acctRoot(accountID, *ledger); + if (acctRoot) { auto const queue = params.isMember(jss::queue) && params[jss::queue].asBool(); @@ -142,26 +135,26 @@ doAccountInfo(RPC::JsonContext& context) } Json::Value jvAccepted(Json::objectValue); - injectSLE(jvAccepted, *sleAccepted); + injectSLE(jvAccepted, acctRoot); result[jss::account_data] = jvAccepted; Json::Value acctFlags{Json::objectValue}; for (auto const& lsf : lsFlags) - acctFlags[lsf.first.data()] = sleAccepted->isFlag(lsf.second); + acctFlags[lsf.first.data()] = acctRoot->isFlag(lsf.second); for (auto const& lsf : disallowIncomingFlags) - acctFlags[lsf.first.data()] = sleAccepted->isFlag(lsf.second); + acctFlags[lsf.first.data()] = acctRoot->isFlag(lsf.second); if (ledger->rules().enabled(featureClawback)) { acctFlags[allowTrustLineClawbackFlag.first.data()] = - sleAccepted->isFlag(allowTrustLineClawbackFlag.second); + acctRoot->isFlag(allowTrustLineClawbackFlag.second); } if (ledger->rules().enabled(featureTokenEscrow)) { acctFlags[allowTrustLineLockingFlag.first.data()] = - sleAccepted->isFlag(allowTrustLineLockingFlag.second); + acctRoot->isFlag(allowTrustLineLockingFlag.second); } result[jss::account_flags] = std::move(acctFlags); @@ -169,7 +162,7 @@ doAccountInfo(RPC::JsonContext& context) auto const pseudoFields = getPseudoAccountFields(); for (auto const& pseudoField : pseudoFields) { - if (sleAccepted->isFieldPresent(*pseudoField)) + if (acctRoot->isFieldPresent(*pseudoField)) { std::string name = pseudoField->fieldName; if (name.ends_with("ID")) diff --git a/src/xrpld/rpc/handlers/DepositAuthorized.cpp b/src/xrpld/rpc/handlers/DepositAuthorized.cpp index b2fc13415e..7de6428d4c 100644 --- a/src/xrpld/rpc/handlers/DepositAuthorized.cpp +++ b/src/xrpld/rpc/handlers/DepositAuthorized.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -66,14 +67,14 @@ doDepositAuthorized(RPC::JsonContext& context) } // If destination account is not in the ledger you can't deposit to it, eh? - auto const sleDest = ledger->read(keylet::account(dstAcct)); - if (!sleDest) + AccountRoot const acctDest(dstAcct, *ledger); + if (!acctDest) { RPC::inject_error(rpcDST_ACT_NOT_FOUND, result); return result; } - bool const reqAuth = ((sleDest->getFlags() & lsfDepositAuth) != 0u) && (srcAcct != dstAcct); + bool const reqAuth = (acctDest->getFlags() & lsfDepositAuth) && (srcAcct != dstAcct); bool const credentialsPresent = params.isMember(jss::credentials); std::set> sorted; diff --git a/src/xrpld/rpc/handlers/NoRippleCheck.cpp b/src/xrpld/rpc/handlers/NoRippleCheck.cpp index a0f797214d..321135d352 100644 --- a/src/xrpld/rpc/handlers/NoRippleCheck.cpp +++ b/src/xrpld/rpc/handlers/NoRippleCheck.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -99,15 +100,15 @@ doNoRippleCheck(RPC::JsonContext& context) return result; } auto const accountID{std::move(id.value())}; - auto const sle = ledger->read(keylet::account(accountID)); - if (!sle) + AccountRoot const acct(accountID, *ledger); + if (!acct) return rpcError(rpcACT_NOT_FOUND); - std::uint32_t seq = sle->getFieldU32(sfSequence); + std::uint32_t seq = acct->getFieldU32(sfSequence); Json::Value& problems = (result["problems"] = Json::arrayValue); - bool bDefaultRipple = (sle->getFieldU32(sfFlags) & lsfDefaultRipple) != 0u; + bool bDefaultRipple = acct->getFieldU32(sfFlags) & lsfDefaultRipple; if ((static_cast(bDefaultRipple) & static_cast(!roleGateway)) != 0) { diff --git a/src/xrpld/rpc/handlers/Simulate.cpp b/src/xrpld/rpc/handlers/Simulate.cpp index 1d46f72425..aee960e05c 100644 --- a/src/xrpld/rpc/handlers/Simulate.cpp +++ b/src/xrpld/rpc/handlers/Simulate.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -38,9 +39,8 @@ getAutofillSequence(Json::Value const& tx_json, RPC::JsonContext& context) return Unexpected( RPC::make_error(rpcSRC_ACT_MALFORMED, RPC::invalid_field_message("tx.Account"))); } - std::shared_ptr const sle = - context.app.openLedger().current()->read(keylet::account(*srcAddressID)); - if (!hasTicketSeq && !sle) + AccountRoot const acct(*srcAddressID, *context.app.openLedger().current()); + if (!hasTicketSeq && !acct) { JLOG(context.app.journal("Simulate").debug()) << "Failed to find source account " @@ -49,7 +49,7 @@ getAutofillSequence(Json::Value const& tx_json, RPC::JsonContext& context) return Unexpected(rpcError(rpcSRC_ACT_NOT_FOUND)); } - return hasTicketSeq ? 0 : context.app.getTxQ().nextQueuableSeq(sle).value(); + return hasTicketSeq ? 0 : context.app.getTxQ().nextQueuableSeq(acct.sle()).value(); } static std::optional