diff --git a/.cspell.config.yaml b/.cspell.config.yaml index 8929973e8a..c1af739255 100644 --- a/.cspell.config.yaml +++ b/.cspell.config.yaml @@ -366,7 +366,6 @@ words: - venv - vfalco - vinnie - - vkeylet - wasmi - wextra - wptr diff --git a/include/xrpl/ledger/helpers/CredentialHelpers.h b/include/xrpl/ledger/helpers/CredentialHelpers.h index 6d235b4316..8b1c819bf4 100644 --- a/include/xrpl/ledger/helpers/CredentialHelpers.h +++ b/include/xrpl/ledger/helpers/CredentialHelpers.h @@ -14,7 +14,6 @@ #include #include -#include #include #include #include @@ -34,32 +33,6 @@ checkExpired(SLE const& sleCredential, NetClock::time_point const& closed); [[nodiscard]] TER deleteSLE(ApplyView& view, SLE::ref sleCredential, beast::Journal j); -/** - * @brief Remove credentials pinned to a pseudo-account's owner directory. - * - * Cleans up credentials that were linked to a pseudo-account (Vault, LoanBroker, - * AMM), which such an account can neither accept nor delete. Only credentials - * are removed; every other object is left in place. The walk visits at most - * @p maxNodesToDelete directory entries and charges the ones it leaves alone - * against that budget too, so a directory holding other objects yields fewer - * than @p maxNodesToDelete deletions. On reaching the bound the result is - * `tecINCOMPLETE` and the caller must propagate it so a later transaction - * resumes. - * - * @param view Mutable ledger view. - * @param pseudoAcct The pseudo-account whose directory is cleaned. - * @param maxNodesToDelete Upper bound on directory entries processed in one call. - * @param j Journal for diagnostics. - * @return tesSUCCESS once no credentials remain, tecINCOMPLETE if the bound was - * reached, or a deletion error. - */ -[[nodiscard]] TER -deletePseudoAccountCredentials( - ApplyView& view, - AccountID const& pseudoAcct, - std::uint16_t maxNodesToDelete, - beast::Journal j); - // Amendment and parameters checks for sfCredentialIDs field NotTEC checkFields(STTx const& tx, Rules const& rules, beast::Journal j); diff --git a/include/xrpl/protocol/Protocol.h b/include/xrpl/protocol/Protocol.h index 8edd4bf4fd..ec9b9ba70a 100644 --- a/include/xrpl/protocol/Protocol.h +++ b/include/xrpl/protocol/Protocol.h @@ -407,16 +407,6 @@ using TxID = uint256; */ constexpr std::uint16_t kMaxDeletableAmmTrustLines = 512; -/** - * The maximum number of owner-directory entries to walk when clearing - * credentials pinned to a pseudo-account, in a single transaction. - * - * The walk stops after this many entries whether or not each one turns out to - * be a credential, so a directory that also holds other objects yields fewer - * deletions per transaction. - */ -constexpr std::uint16_t kMaxDeletablePseudoAccountCredentials = 512; - /** * The maximum length of a URI inside an Oracle */ diff --git a/src/libxrpl/ledger/helpers/AMMHelpers.cpp b/src/libxrpl/ledger/helpers/AMMHelpers.cpp index 20a793e4cb..fcad22d2d5 100644 --- a/src/libxrpl/ledger/helpers/AMMHelpers.cpp +++ b/src/libxrpl/ledger/helpers/AMMHelpers.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -691,12 +690,6 @@ deleteAMMTrustLines( return {deleteAMMTrustLine(sb, sleItem, ammAccountID, j), SkipEntry::No}; } - // A credential naming the pseudo-account as subject can't be - // accepted or deleted by it and would otherwise permanently pin the - // AMM. Clean it up here, inside the same bounded walk, so the - // pinned AMM can still be deleted. - if (sb.rules().enabled(fixCleanup3_4_0) && nodeType == ltCREDENTIAL) - return {credentials::deleteSLE(sb, sleItem, j), SkipEntry::No}; // LCOV_EXCL_START JLOG(j.error()) << "deleteAMMObjects: deleting non-trustline or non-MPT " << nodeType; return {tecINTERNAL, SkipEntry::No}; @@ -774,8 +767,6 @@ deleteAMMAccount(Sandbox& sb, Asset const& asset, Asset const& asset2, beast::Jo // LCOV_EXCL_STOP } - // deleteAMMTrustLines also removes any credentials pinned to the AMM - // pseudo-account, within its bounded walk. if (auto const ter = deleteAMMTrustLines(sb, ammAccountID, kMaxDeletableAmmTrustLines, j); !isTesSuccess(ter)) return ter; @@ -917,11 +908,6 @@ isOnlyLiquidityProvider(ReadView const& view, Issue const& ammIssue, AccountID c ++nMPT; continue; } - // A credential naming the pseudo-account as subject can be pinned - // to its owner directory. Ignore it here; deleteAMMTrustLines - // removes it when the AMM is deleted. - if (view.rules().enabled(fixCleanup3_4_0) && entryType == ltCREDENTIAL) - continue; if (entryType != ltRIPPLE_STATE) return std::unexpected(tecINTERNAL); // LCOV_EXCL_LINE auto const lowLimit = sle->getFieldAmount(sfLowLimit); diff --git a/src/libxrpl/ledger/helpers/CredentialHelpers.cpp b/src/libxrpl/ledger/helpers/CredentialHelpers.cpp index 9c3ca4ec78..5ba832957d 100644 --- a/src/libxrpl/ledger/helpers/CredentialHelpers.cpp +++ b/src/libxrpl/ledger/helpers/CredentialHelpers.cpp @@ -5,10 +5,8 @@ #include #include #include -#include #include #include -#include #include #include #include @@ -129,36 +127,6 @@ deleteSLE(ApplyView& view, SLE::ref sleCredential, beast::Journal j) return tesSUCCESS; } -TER -deletePseudoAccountCredentials( - ApplyView& view, - AccountID const& pseudoAcct, - std::uint16_t maxNodesToDelete, - beast::Journal j) -{ - XRPL_ASSERT( - isPseudoAccount(view.read(keylet::account(pseudoAcct))), - "xrpl::credentials::deletePseudoAccountCredentials : is a pseudo-account"); - - // Delete the credentials linked into the pseudo-account's owner directory, - // visiting at most maxNodesToDelete entries. Any other object is left in - // place; the caller's own checks decide whether the remaining directory - // blocks deletion. If the bound is reached, cleanupOnAccountDelete returns - // tecINCOMPLETE and the caller propagates it so a later transaction resumes. - return cleanupOnAccountDelete( - view, - keylet::ownerDir(pseudoAcct), - [&view, &j](LedgerEntryType nodeType, uint256 const&, SLE::pointer& sleItem) - -> std::pair { - if (nodeType == ltCREDENTIAL) - return {deleteSLE(view, sleItem, j), SkipEntry::No}; - - return {tesSUCCESS, SkipEntry::Yes}; - }, - j, - maxNodesToDelete); -} - NotTEC checkFields(STTx const& tx, Rules const& rules, beast::Journal j) { diff --git a/src/libxrpl/tx/Transactor.cpp b/src/libxrpl/tx/Transactor.cpp index 63092cc128..6bf99e567d 100644 --- a/src/libxrpl/tx/Transactor.cpp +++ b/src/libxrpl/tx/Transactor.cpp @@ -1246,7 +1246,7 @@ removeExpiredNFTokenOffers( } static void -removeDeletedCredentials(ApplyView& view, std::vector const& creds, beast::Journal viewJ) +removeExpiredCredentials(ApplyView& view, std::vector const& creds, beast::Journal viewJ) { for (auto const& index : creds) { @@ -1255,7 +1255,7 @@ removeDeletedCredentials(ApplyView& view, std::vector const& creds, bea if (auto const ter = credentials::deleteSLE(view, sle, viewJ); !isTesSuccess(ter)) { JLOG(viewJ.error()) - << "removeDeletedCredentials: failed to delete credential. Err: " + << "removeExpiredCredentials: failed to delete expired credential. Err: " << transToken(ter); } } @@ -1437,8 +1437,7 @@ Transactor::processPersistentChanges(TER result, XRPAmount fee) // should be used, making it possible to do more useful work // when transactions fail with a `tec` code. - auto typesForResult = [credentialCleanup = - view().rules().enabled(fixCleanup3_4_0)](TER const ter) { + auto typesForResult = [](TER const ter) { std::unordered_set types; if ((ter == tecOVERSIZE) || (ter == tecKILLED)) { @@ -1447,11 +1446,6 @@ Transactor::processPersistentChanges(TER result, XRPAmount fee) else if (ter == tecINCOMPLETE) { types.insert(ltRIPPLE_STATE); - // A bounded pseudo-account credential cleanup (VaultDelete / - // LoanBrokerDelete) persists its partial credential deletions so a - // later transaction can resume. - if (credentialCleanup) - types.insert(ltCREDENTIAL); } else if (ter == tecEXPIRED) { @@ -1529,7 +1523,7 @@ Transactor::processPersistentChanges(TER result, XRPAmount fee) removeDeletedTrustLines(view(), ids, viewJ); break; case ltCREDENTIAL: - removeDeletedCredentials(view(), ids, viewJ); + removeExpiredCredentials(view(), ids, viewJ); break; // LCOV_EXCL_START default: diff --git a/src/libxrpl/tx/invariants/MPTInvariant.cpp b/src/libxrpl/tx/invariants/MPTInvariant.cpp index 09b4308165..e38e8f2b93 100644 --- a/src/libxrpl/tx/invariants/MPTInvariant.cpp +++ b/src/libxrpl/tx/invariants/MPTInvariant.cpp @@ -234,14 +234,6 @@ ValidMPTIssuance::finalize( if (hasPrivilege(tx, Privilege::DestroyMptIssuance)) { - // A VaultDelete that is still cleaning up credentials pinned to its - // pseudo-account returns tecINCOMPLETE and has not yet reached the - // share issuance. Don't require the issuance to be removed until - // the deletion completes (a later transaction). - if (rules.enabled(fixCleanup3_4_0) && txnType == ttVAULT_DELETE && - result == tecINCOMPLETE) - return mptIssuancesDeleted_ == 0 && mptIssuancesCreated_ == 0; - if (mptIssuancesDeleted_ == 0) { JLOG(j.fatal()) << "Invariant failed: MPT issuance deletion " diff --git a/src/libxrpl/tx/transactors/lending/LoanBrokerDelete.cpp b/src/libxrpl/tx/transactors/lending/LoanBrokerDelete.cpp index 06907ce366..433d77806a 100644 --- a/src/libxrpl/tx/transactors/lending/LoanBrokerDelete.cpp +++ b/src/libxrpl/tx/transactors/lending/LoanBrokerDelete.cpp @@ -4,13 +4,11 @@ #include #include #include -#include #include #include #include #include #include -#include #include #include #include @@ -142,19 +140,6 @@ LoanBrokerDelete::doApply() auto const brokerPseudoID = broker->at(sfAccount); - // Remove any credentials pinned to the broker pseudo-account before anything - // else. They would otherwise keep its owner directory alive and block - // deletion with tecHAS_OBLIGATIONS. Doing it first means a bounded, - // tecINCOMPLETE cleanup can be resumed by a later transaction without having - // already torn down the broker. - if (view().rules().enabled(fixCleanup3_4_0)) - { - if (auto const ter = credentials::deletePseudoAccountCredentials( - view(), brokerPseudoID, kMaxDeletablePseudoAccountCredentials, j_); - !isTesSuccess(ter)) - return ter; - } - if (!view().dirRemove( keylet::ownerDir(accountID_), broker->at(sfOwnerNode), broker->key(), false)) { diff --git a/src/libxrpl/tx/transactors/vault/VaultDelete.cpp b/src/libxrpl/tx/transactors/vault/VaultDelete.cpp index 35bf80c29f..9c6c41654b 100644 --- a/src/libxrpl/tx/transactors/vault/VaultDelete.cpp +++ b/src/libxrpl/tx/transactors/vault/VaultDelete.cpp @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include @@ -102,19 +101,6 @@ VaultDelete::doApply() if (!vault) return tefINTERNAL; // LCOV_EXCL_LINE - // Remove any credentials pinned to the vault pseudo-account before anything - // else. They would otherwise keep its owner directory alive and block - // deletion with tecHAS_OBLIGATIONS. Doing it first means a bounded, - // tecINCOMPLETE cleanup can be resumed by a later transaction without having - // already torn down the vault. - if (view().rules().enabled(fixCleanup3_4_0)) - { - if (auto const ter = credentials::deletePseudoAccountCredentials( - view(), vault->at(sfAccount), kMaxDeletablePseudoAccountCredentials, j_); - !isTesSuccess(ter)) - return ter; - } - // Destroy the asset holding. auto asset = vault->at(sfAsset); diff --git a/src/test/app/AMM_test.cpp b/src/test/app/AMM_test.cpp index a1d5260606..0212035c6e 100644 --- a/src/test/app/AMM_test.cpp +++ b/src/test/app/AMM_test.cpp @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include @@ -5193,51 +5192,6 @@ private: {features}); } - void - testCredentialPinsPseudoAccount() - { - testcase("Credential pins AMM pseudo-account"); - - using namespace jtx; - FeatureBitset const all{testableAmendments()}; - - // A credential issued to an AMM pseudo-account can't be accepted or - // deleted by it. A pin created before the cure activates stays pinned - // in the pseudo-account's owner directory and makes AMM deletion fail - // with tecINTERNAL (deleteAMMTrustLines rejects the unexpected - // directory entry). - Account const attacker{"attacker"}; - char const credType[] = "FN36"; - - Env env(*this, all - fixCleanup3_3_0 - fixCleanup3_4_0); - fund(env, gw_, {alice_}, XRP(20'000), {USD(10'000)}); - env.fund(XRP(1'000), attacker); - env.close(); - - AMM amm(env, alice_, XRP(10'000), USD(10'000)); - Account const ammAcct{"amm pseudo-account", amm.ammAccount()}; - env.memoize(ammAcct); - - env(credentials::create(ammAcct, attacker, credType)); - env.close(); - auto const credKey = credentials::keylet(ammAcct, attacker, credType); - BEAST_EXPECT(env.le(credKey)); - - // Emptying the AMM would auto-delete it, but the pinned credential makes - // deleteAMMAccount fail; the withdraw is rolled back and the AMM stays. - amm.withdrawAll(alice_, std::nullopt, Ter(tecINTERNAL)); - BEAST_EXPECT(amm.ammExists()); - - env.enableFeature(fixCleanup3_4_0); - env.close(); - - // The pre-existing pin is cleaned up and the AMM deletes. - amm.withdrawAll(alice_); - BEAST_EXPECT(!amm.ammExists()); - BEAST_EXPECT(!env.le(credKey)); - BEAST_EXPECT(!env.le(keylet::ownerDir(amm.ammAccount()))); - } - void testAutoDelete() { @@ -7505,7 +7459,6 @@ private: FeatureBitset const all{testableAmendments()}; testInvalidInstance(); testInstanceCreate(); - testCredentialPinsPseudoAccount(); for (auto const& f : amendmentCombinations({fixCleanup3_3_0, featureAMMClawback})) testInvalidDeposit(f); testDeposit(); diff --git a/src/test/app/lending/LoanBroker_test.cpp b/src/test/app/lending/LoanBroker_test.cpp index 5b3ea854f8..3bcda42c7e 100644 --- a/src/test/app/lending/LoanBroker_test.cpp +++ b/src/test/app/lending/LoanBroker_test.cpp @@ -2968,126 +2968,6 @@ class LoanBroker_test : public beast::unit_test::Suite runTestCases(all_ - fixCleanup3_2_0); } - void - testCredentialPinsPseudoAccount() - { - using namespace test::jtx; - using namespace loan_broker; - - // A credential issued to a LoanBroker pseudo-account can't be accepted - // or deleted by it, so it stays pinned in the pseudo-account's owner - // directory and blocks LoanBrokerDelete with tecHAS_OBLIGATIONS. A pin - // created before the cure activates is removed by LoanBrokerDelete once - // it does. - Account const alice{"alice"}; // vault & broker owner - Account const attacker{"attacker"}; - char const credType[] = "FN36"; - - Env env{*this, all_ - fixCleanup3_3_0 - fixCleanup3_4_0}; - env.fund(XRP(1'000'000), alice, attacker); - env.close(); - - Vault const vault{env}; - auto [vtx, vkeylet] = vault.create({.owner = alice, .asset = xrpIssue()}); - env(vtx); - env.close(); - BEAST_EXPECT(env.le(vkeylet)); - - auto const brokerKeylet = - keylet::loanBroker(alice.id(), SeqProxy::rawSequence(env.seq(alice))); - env(set(alice.id(), vkeylet.key)); - env.close(); - - auto const broker = env.le(brokerKeylet); - BEAST_EXPECT(broker); - Account const pseudo{"broker pseudo-account", broker->at(sfAccount)}; - env.memoize(pseudo); - - testcase("Credential pins broker pseudo-account"); - env(credentials::create(pseudo, attacker, credType)); - env.close(); - - auto const credKey = credentials::keylet(pseudo, attacker, credType); - BEAST_EXPECT(env.le(credKey)); - BEAST_EXPECT(ownerCount(env, attacker) == 1); - - env(del(alice.id(), brokerKeylet.key), Ter(tecHAS_OBLIGATIONS)); - env.close(); - - env.enableFeature(fixCleanup3_4_0); - env.close(); - - // The pre-existing pin no longer blocks deletion; the credential is - // cleaned up and the issuer's owner count is restored. - testcase("LoanBrokerDelete removes pinned credential"); - env(del(alice.id(), brokerKeylet.key)); - env.close(); - - BEAST_EXPECT(!env.le(credKey)); - BEAST_EXPECT(!env.le(brokerKeylet)); - BEAST_EXPECT(!env.le(keylet::account(pseudo.id()))); - BEAST_EXPECT(ownerCount(env, attacker) == 0); - } - - void - testCredentialPinOverflow() - { - using namespace test::jtx; - using namespace loan_broker; - testcase("Credential pin cleanup is bounded (tecINCOMPLETE)"); - - // A pseudo-account can be pinned with more credentials than one - // transaction is allowed to clean up. LoanBrokerDelete then removes - // them a bounded batch at a time, returning tecINCOMPLETE until the - // last batch. - Account const alice{"alice"}; - Account const attacker{"attacker"}; - - Env env{*this, all_ - fixCleanup3_3_0 - fixCleanup3_4_0}; - env.fund(XRP(10'000'000), alice, attacker); - env.close(); - - Vault const vault{env}; - auto [vtx, vkeylet] = vault.create({.owner = alice, .asset = xrpIssue()}); - env(vtx); - env.close(); - BEAST_EXPECT(env.le(vkeylet)); - - auto const brokerKeylet = - keylet::loanBroker(alice.id(), SeqProxy::rawSequence(env.seq(alice))); - env(set(alice.id(), vkeylet.key)); - env.close(); - - auto const broker = env.le(brokerKeylet); - BEAST_EXPECT(broker); - Account const pseudo{"broker pseudo-account", broker->at(sfAccount)}; - env.memoize(pseudo); - - // Pin more than one cleanup batch's worth of credentials. - std::uint16_t const count = kMaxDeletablePseudoAccountCredentials + 3; - for (std::uint16_t i = 0; i < count; ++i) - env(credentials::create(pseudo, attacker, std::to_string(i))); - env.close(); - BEAST_EXPECT(ownerCount(env, attacker) == count); - - env.enableFeature(fixCleanup3_4_0); - env.close(); - - // First delete removes one bounded batch and reports it isn't finished. - env(del(alice.id(), brokerKeylet.key), Ter(tecINCOMPLETE)); - env.close(); - BEAST_EXPECT(env.le(brokerKeylet)); // broker still exists - auto const remaining = ownerCount(env, attacker); - BEAST_EXPECT(remaining > 0 && remaining < count); - - // Second delete finishes the cleanup and removes the broker. - env(del(alice.id(), brokerKeylet.key)); - env.close(); - BEAST_EXPECT(!env.le(brokerKeylet)); - BEAST_EXPECT(!env.le(keylet::account(pseudo.id()))); - BEAST_EXPECT(ownerCount(env, attacker) == 0); - } - public: void run() override @@ -3106,8 +2986,6 @@ public: testDisabled(); testLifecycle(); - testCredentialPinsPseudoAccount(); - testCredentialPinOverflow(); testInvalidLoanBrokerDelete(); testInvalidLoanBrokerSet(); testRequireAuth(); diff --git a/src/test/app/vault/VaultBugs_test.cpp b/src/test/app/vault/VaultBugs_test.cpp index 02949b8619..cc30bd6091 100644 --- a/src/test/app/vault/VaultBugs_test.cpp +++ b/src/test/app/vault/VaultBugs_test.cpp @@ -1356,117 +1356,6 @@ private: } } - void - testCredentialPinsPseudoAccount() - { - using namespace test::jtx; - - // A credential issued to a vault pseudo-account can't be accepted or - // deleted by it (pseudo-accounts can't sign), so it stays pinned in the - // pseudo-account's owner directory and blocks VaultDelete with - // tecHAS_OBLIGATIONS. A pin created before the cure activates is removed - // by VaultDelete once it does. - Account const owner{"owner"}; - Account const attacker{"attacker"}; - char const credType[] = "FN36"; - - Env env{*this, all_ - fixCleanup3_3_0 - fixCleanup3_4_0}; - env.fund(XRP(1'000'000), owner, attacker); - env.close(); - - Vault const vault{env}; - PrettyAsset const asset = xrpIssue(); - auto [tx, keylet] = vault.create({.owner = owner, .asset = asset}); - env(tx); - env.close(); - - auto const vaultSle = env.le(keylet); - BEAST_EXPECT(vaultSle); - Account const pseudo{"vault pseudo-account", vaultSle->at(sfAccount)}; - env.memoize(pseudo); - - // The pseudo-account owns the share issuance; the pin must not change - // its owner count (an unaccepted credential is owned by the issuer). - auto const pseudoOwnerCount = ownerCount(env, pseudo); - - testcase("Credential pins vault pseudo-account"); - env(credentials::create(pseudo, attacker, credType)); - env.close(); - - auto const credKey = credentials::keylet(pseudo, attacker, credType); - BEAST_EXPECT(env.le(credKey)); - BEAST_EXPECT(ownerCount(env, attacker) == 1); - BEAST_EXPECT(ownerCount(env, pseudo) == pseudoOwnerCount); - - // The pin blocks deletion of an otherwise-empty vault. - env(vault.del({.owner = owner, .id = keylet.key}), Ter(tecHAS_OBLIGATIONS)); - env.close(); - - env.enableFeature(fixCleanup3_4_0); - env.close(); - - // The pre-existing pin no longer blocks deletion; the credential is - // cleaned up and the issuer's owner count is restored. - testcase("VaultDelete removes pinned credential"); - env(vault.del({.owner = owner, .id = keylet.key})); - env.close(); - - BEAST_EXPECT(!env.le(credKey)); - BEAST_EXPECT(!env.le(keylet)); - BEAST_EXPECT(!env.le(::xrpl::keylet::account(pseudo.id()))); - BEAST_EXPECT(ownerCount(env, attacker) == 0); - } - - void - testCredentialPinOverflow() - { - using namespace test::jtx; - testcase("Credential pin cleanup is bounded (tecINCOMPLETE)"); - - // A pseudo-account can be pinned with more credentials than one - // transaction is allowed to clean up. VaultDelete then removes them a - // bounded batch at a time, returning tecINCOMPLETE until the last batch. - Account const owner{"owner"}; - Account const attacker{"attacker"}; - - Env env{*this, all_ - fixCleanup3_3_0 - fixCleanup3_4_0}; - env.fund(XRP(10'000'000), owner, attacker); - env.close(); - - Vault const vault{env}; - auto [tx, keylet] = vault.create({.owner = owner, .asset = xrpIssue()}); - env(tx); - env.close(); - auto const vaultSle = env.le(keylet); - BEAST_EXPECT(vaultSle); - Account const pseudo{"vault pseudo-account", vaultSle->at(sfAccount)}; - env.memoize(pseudo); - - // Pin more than one cleanup batch's worth of credentials. - std::uint16_t const count = kMaxDeletablePseudoAccountCredentials + 3; - for (std::uint16_t i = 0; i < count; ++i) - env(credentials::create(pseudo, attacker, std::to_string(i))); - env.close(); - BEAST_EXPECT(ownerCount(env, attacker) == count); - - env.enableFeature(fixCleanup3_4_0); - env.close(); - - // First delete removes one bounded batch and reports it isn't finished. - env(vault.del({.owner = owner, .id = keylet.key}), Ter(tecINCOMPLETE)); - env.close(); - BEAST_EXPECT(env.le(keylet)); // vault still exists - auto const remaining = ownerCount(env, attacker); - BEAST_EXPECT(remaining > 0 && remaining < count); - - // Second delete finishes the cleanup and removes the vault. - env(vault.del({.owner = owner, .id = keylet.key})); - env.close(); - BEAST_EXPECT(!env.le(keylet)); - BEAST_EXPECT(!env.le(::xrpl::keylet::account(pseudo.id()))); - BEAST_EXPECT(ownerCount(env, attacker) == 0); - } - struct ImpairedLoanVault { test::jtx::Account issuer; @@ -2867,8 +2756,6 @@ public: testBugVaultDepositOvercreditsAcrossScaleBoundary(); testBugVaultLockedByPartialWithdraw(); testVaultDepositNegativeBalanceFromOppositeLimit(); - testCredentialPinsPseudoAccount(); - testCredentialPinOverflow(); testBug6LimitBypassWithShares(); testBugClawbackRoundTripOvershoot(); testBugWithdrawRoundTripOvershoot();