diff --git a/Builds/CMake/RippledCore.cmake b/Builds/CMake/RippledCore.cmake index 84371a3dac4..915ecc0b412 100644 --- a/Builds/CMake/RippledCore.cmake +++ b/Builds/CMake/RippledCore.cmake @@ -682,7 +682,6 @@ target_sources (rippled PRIVATE src/ripple/rpc/handlers/BlackList.cpp src/ripple/rpc/handlers/BookOffers.cpp src/ripple/rpc/handlers/CanDelete.cpp - src/ripple/rpc/handlers/MPTHolders.cpp src/ripple/rpc/handlers/Connect.cpp src/ripple/rpc/handlers/ConsensusInfo.cpp src/ripple/rpc/handlers/CrawlShards.cpp diff --git a/src/ripple/app/tx/impl/MPTokenAuthorize.cpp b/src/ripple/app/tx/impl/MPTokenAuthorize.cpp index 529aa0499d2..fb32c55ca80 100644 --- a/src/ripple/app/tx/impl/MPTokenAuthorize.cpp +++ b/src/ripple/app/tx/impl/MPTokenAuthorize.cpp @@ -182,13 +182,6 @@ MPTokenAuthorize::doApply() false)) return tecINTERNAL; - if (!view().dirRemove( - keylet::mpt_dir(mptIssuanceID), - (*sleMpt)[sfMPTokenNode], - sleMpt->key(), - false)) - return tecINTERNAL; - adjustOwnerCount(view(), sleAcct, -1, j_); view().erase(sleMpt); @@ -214,22 +207,11 @@ MPTokenAuthorize::doApply() if (!ownerNode) return tecDIR_FULL; - auto const mptNode = view().dirInsert( - keylet::mpt_dir(mptIssuanceID), - mptokenKey, - [&mptIssuanceID](std::shared_ptr const& sle) { - (*sle)[sfMPTokenIssuanceID] = mptIssuanceID; - }); - - if (!mptNode) - return tecDIR_FULL; - auto mptoken = std::make_shared(mptokenKey); (*mptoken)[sfAccount] = account_; (*mptoken)[sfMPTokenIssuanceID] = mptIssuanceID; (*mptoken)[sfFlags] = 0; (*mptoken)[sfOwnerNode] = *ownerNode; - (*mptoken)[sfMPTokenNode] = *mptNode; view().insert(mptoken); // Update owner count. diff --git a/src/ripple/protocol/SField.h b/src/ripple/protocol/SField.h index 08f90237973..6a9eb31723d 100644 --- a/src/ripple/protocol/SField.h +++ b/src/ripple/protocol/SField.h @@ -451,7 +451,6 @@ extern SF_UINT64 const sfCookie; extern SF_UINT64 const sfServerVersion; extern SF_UINT64 const sfNFTokenOfferNode; extern SF_UINT64 const sfEmitBurden; -extern SF_UINT64 const sfMPTokenNode; // 64-bit integers (uncommon) extern SF_UINT64 const sfHookOn; diff --git a/src/ripple/protocol/impl/LedgerFormats.cpp b/src/ripple/protocol/impl/LedgerFormats.cpp index c20af507cf2..d7f3387b47e 100644 --- a/src/ripple/protocol/impl/LedgerFormats.cpp +++ b/src/ripple/protocol/impl/LedgerFormats.cpp @@ -74,7 +74,6 @@ LedgerFormats::LedgerFormats() {sfIndexNext, soeOPTIONAL}, {sfIndexPrevious, soeOPTIONAL}, {sfNFTokenID, soeOPTIONAL}, - {sfMPTokenIssuanceID, soeOPTIONAL}, }, commonFields); @@ -366,7 +365,6 @@ LedgerFormats::LedgerFormats() {sfMPTAmount, soeDEFAULT}, {sfLockedAmount, soeDEFAULT}, {sfOwnerNode, soeREQUIRED}, - {sfMPTokenNode, soeREQUIRED}, {sfPreviousTxnID, soeREQUIRED}, {sfPreviousTxnLgrSeq, soeREQUIRED} }, diff --git a/src/ripple/protocol/impl/SField.cpp b/src/ripple/protocol/impl/SField.cpp index fea6f010527..3b3f309d382 100644 --- a/src/ripple/protocol/impl/SField.cpp +++ b/src/ripple/protocol/impl/SField.cpp @@ -180,7 +180,6 @@ CONSTRUCT_TYPED_SFIELD(sfCookie, "Cookie", UINT64, CONSTRUCT_TYPED_SFIELD(sfServerVersion, "ServerVersion", UINT64, 11); CONSTRUCT_TYPED_SFIELD(sfNFTokenOfferNode, "NFTokenOfferNode", UINT64, 12); CONSTRUCT_TYPED_SFIELD(sfEmitBurden, "EmitBurden", UINT64, 13); -CONSTRUCT_TYPED_SFIELD(sfMPTokenNode, "MPTokenNode", UINT64, 14); // 64-bit integers (uncommon) CONSTRUCT_TYPED_SFIELD(sfHookOn, "HookOn", UINT64, 16); diff --git a/src/ripple/rpc/handlers/MPTHolders.cpp b/src/ripple/rpc/handlers/MPTHolders.cpp deleted file mode 100644 index 64cb3f4f25b..00000000000 --- a/src/ripple/rpc/handlers/MPTHolders.cpp +++ /dev/null @@ -1,164 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of rippled: https://github.com/ripple/rippled - Copyright (c) 2024 Ripple Labs Inc. - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace ripple { - -static void -appendMPTHolderJson( - Application const& app, - std::shared_ptr const& mpt, - Json::Value& holders) -{ - Json::Value& obj(holders.append(Json::objectValue)); - - obj[jss::mptoken_index] = to_string(mpt->key()); - obj[jss::flags] = (*mpt)[sfFlags]; - obj[jss::account] = toBase58(mpt->getAccountID(sfAccount)); - obj[jss::mpt_amount] = - STUInt64{(*mpt)[sfMPTAmount]}.getJson(JsonOptions::none); - - if ((*mpt)[sfLockedAmount]) - obj[jss::locked_amount] = - STUInt64{(*mpt)[sfLockedAmount]}.getJson(JsonOptions::none); -} - -// { -// mpt_issuance_id: -// ledger_hash : -// ledger_index : -// limit: integer // optional -// marker: opaque // optional, resume previous query -// } -static Json::Value -enumerateMPTHolders( - RPC::JsonContext& context, - uint192 const& mptIssuanceID, - Keylet const& directory) -{ - unsigned int limit; - if (auto err = readLimitField(limit, RPC::Tuning::mptHolders, context)) - return *err; - - std::shared_ptr ledger; - - if (auto result = RPC::lookupLedger(ledger, context); !ledger) - return result; - - if (!ledger->exists(directory)) - return rpcError(rpcOBJECT_NOT_FOUND); - - Json::Value result; - result[jss::mpt_issuance_id] = to_string(mptIssuanceID); - - Json::Value& jsonHolders(result[jss::holders] = Json::arrayValue); - - std::vector> holders; - unsigned int reserve(limit); - uint256 startAfter; - std::uint64_t startHint = 0; - - if (context.params.isMember(jss::marker)) - { - // We have a start point. Use limit - 1 from the result and use the - // very last one for the resume. - Json::Value const& marker(context.params[jss::marker]); - - if (!marker.isString()) - return RPC::expected_field_error(jss::marker, "string"); - - if (!startAfter.parseHex(marker.asString())) - return rpcError(rpcINVALID_PARAMS); - - auto const sle = ledger->read(keylet::mptoken(startAfter)); - - if (!sle || mptIssuanceID != sle->getFieldH192(sfMPTokenIssuanceID)) - return rpcError(rpcINVALID_PARAMS); - - startHint = sle->getFieldU64(sfMPTokenNode); - appendMPTHolderJson(context.app, sle, jsonHolders); - holders.reserve(reserve); - } - else - { - // We have no start point, limit should be one higher than requested. - holders.reserve(++reserve); - } - - if (!forEachItemAfter( - *ledger, - directory, - startAfter, - startHint, - reserve, - [&holders](std::shared_ptr const& mptoken) { - if (mptoken->getType() == ltMPTOKEN) - { - holders.emplace_back(mptoken); - return true; - } - - return false; - })) - { - return rpcError(rpcINVALID_PARAMS); - } - - if (holders.size() == reserve) - { - result[jss::limit] = limit; - result[jss::marker] = to_string(holders.back()->key()); - holders.pop_back(); - } - - for (auto const& mpt : holders) - appendMPTHolderJson(context.app, mpt, jsonHolders); - - context.loadType = Resource::feeMediumBurdenRPC; - return result; -} - -Json::Value -doMPTHolders(RPC::JsonContext& context) -{ - if (!context.params.isMember(jss::mpt_issuance_id)) - return RPC::missing_field_error(jss::mpt_issuance_id); - - uint192 mptIssuanceID; - - if (!mptIssuanceID.parseHex( - context.params[jss::mpt_issuance_id].asString())) - return RPC::invalid_field_error(jss::mpt_issuance_id); - - return enumerateMPTHolders( - context, mptIssuanceID, keylet::mpt_dir(mptIssuanceID)); -} - -} // namespace ripple diff --git a/src/ripple/rpc/impl/Handler.cpp b/src/ripple/rpc/impl/Handler.cpp index 4cccc060180..3c9cb463def 100644 --- a/src/ripple/rpc/impl/Handler.cpp +++ b/src/ripple/rpc/impl/Handler.cpp @@ -95,7 +95,7 @@ Handler const handlerArray[]{ {"book_changes", byRef(&doBookChanges), Role::USER, NO_CONDITION}, {"book_offers", byRef(&doBookOffers), Role::USER, NO_CONDITION}, {"can_delete", byRef(&doCanDelete), Role::ADMIN, NO_CONDITION}, - {"mpt_holders", byRef(&doMPTHolders), Role::USER, NO_CONDITION}, + //{"mpt_holders", byRef(&doMPTHolders), Role::ADMIN, NO_CONDITION}, {"channel_authorize", byRef(&doChannelAuthorize), Role::USER, NO_CONDITION}, {"channel_verify", byRef(&doChannelVerify), Role::USER, NO_CONDITION}, {"connect", byRef(&doConnect), Role::ADMIN, NO_CONDITION}, diff --git a/src/test/app/MPToken_test.cpp b/src/test/app/MPToken_test.cpp index f2b27a81bdd..dd3fcece849 100644 --- a/src/test/app/MPToken_test.cpp +++ b/src/test/app/MPToken_test.cpp @@ -776,175 +776,6 @@ class MPToken_test : public beast::unit_test::suite meta[jss::mpt_issuance_id] == to_string(mptAlice.issuanceID())); } - void - testMPTHoldersAPI(FeatureBitset features) - { - testcase("MPT Holders"); - using namespace test::jtx; - - // a lambda that checks API correctness given different numbers of - // MPToken - auto checkMPTokens = [&](int expectCount, - int expectMarkerCount, - int line) { - Env env{*this, features}; - Account const alice("alice"); // issuer - - MPTTester mptAlice(env, alice); - - mptAlice.create(); - - // create accounts that will create MPTokens - for (auto i = 0; i < expectCount; i++) - { - Account const bob{std::string("bob") + std::to_string(i)}; - env.fund(XRP(1000), bob); - env.close(); - - // a holder creates a mptoken - mptAlice.authorize({.account = &bob}); - } - - // Checks mpt_holder query responses - { - int markerCount = 0; - Json::Value allHolders(Json::arrayValue); - std::string marker; - - // The do/while collects results until no marker is - // returned. - do - { - Json::Value mptHolders = [&env, &mptAlice, &marker]() { - Json::Value params; - params[jss::mpt_issuance_id] = - to_string(mptAlice.issuanceID()); - - if (!marker.empty()) - params[jss::marker] = marker; - return env.rpc( - "json", "mpt_holders", to_string(params)); - }(); - - // If there are mptokens we get an error - if (expectCount == 0) - { - if (expect( - mptHolders.isMember(jss::result), - "expected \"result\"", - __FILE__, - line)) - { - if (expect( - mptHolders[jss::result].isMember( - jss::error), - "expected \"error\"", - __FILE__, - line)) - { - expect( - mptHolders[jss::result][jss::error] - .asString() == "objectNotFound", - "expected \"objectNotFound\"", - __FILE__, - line); - } - } - break; - } - - marker.clear(); - if (expect( - mptHolders.isMember(jss::result), - "expected \"result\"", - __FILE__, - line)) - { - Json::Value& result = mptHolders[jss::result]; - - if (result.isMember(jss::marker)) - { - ++markerCount; - marker = result[jss::marker].asString(); - } - - if (expect( - result.isMember(jss::holders), - "expected \"holders\"", - __FILE__, - line)) - { - Json::Value& someHolders = result[jss::holders]; - for (std::size_t i = 0; i < someHolders.size(); ++i) - allHolders.append(someHolders[i]); - } - } - } while (!marker.empty()); - - // Verify the contents of allHolders makes sense. - expect( - allHolders.size() == expectCount, - "Unexpected returned offer count", - __FILE__, - line); - expect( - markerCount == expectMarkerCount, - "Unexpected marker count", - __FILE__, - line); - std::optional globalFlags; - std::set mptIndexes; - std::set holderAddresses; - for (Json::Value const& holder : allHolders) - { - // The flags on all found offers should be the same. - if (!globalFlags) - globalFlags = holder[jss::flags].asInt(); - - expect( - *globalFlags == holder[jss::flags].asInt(), - "Inconsistent flags returned", - __FILE__, - line); - - // The test conditions should produce unique indexes and - // amounts for all holders. - mptIndexes.insert(holder[jss::mptoken_index].asString()); - holderAddresses.insert(holder[jss::account].asString()); - } - - expect( - mptIndexes.size() == expectCount, - "Duplicate indexes returned?", - __FILE__, - line); - expect( - holderAddresses.size() == expectCount, - "Duplicate addresses returned?", - __FILE__, - line); - } - }; - - // Test 1 MPToken - checkMPTokens(1, 0, __LINE__); - - // Test 10 MPTokens - checkMPTokens(10, 0, __LINE__); - - // Test 200 MPTokens - checkMPTokens(200, 0, __LINE__); - - // Test 201 MPTokens - checkMPTokens(201, 1, __LINE__); - - // Test 400 MPTokens - checkMPTokens(400, 1, __LINE__); - - // Test 401 MPTokesn - checkMPTokens(401, 2, __LINE__); - } - public: void run() override @@ -981,9 +812,6 @@ class MPToken_test : public beast::unit_test::suite // `subscribe`, `ledger`. We should create test for these // occurances (lower prioirity). testTxJsonMetaFields(all); - - // Test mpt_holders - testMPTHoldersAPI(all); } };