mirror of
				https://github.com/XRPLF/rippled.git
				synced 2025-11-04 11:15:56 +00:00 
			
		
		
		
	Compare commits
	
		
			64 Commits
		
	
	
		
			ximinez/le
			...
			945c362559
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					945c362559 | ||
| 
						 | 
					9546c52013 | ||
| 
						 | 
					3a099aeb64 | ||
| 
						 | 
					8567bd0d12 | ||
| 
						 | 
					3cb1851537 | ||
| 
						 | 
					55feea308e | ||
| 
						 | 
					a6692af17a | ||
| 
						 | 
					1d058a5d78 | ||
| 
						 | 
					a70821adc5 | ||
| 
						 | 
					bfeb60d3f5 | ||
| 
						 | 
					c86bfa32f7 | ||
| 
						 | 
					0f44d619b6 | ||
| 
						 | 
					2add6a7917 | ||
| 
						 | 
					d21c4f3218 | ||
| 
						 | 
					265a504301 | ||
| 
						 | 
					b1e576d3d1 | ||
| 
						 | 
					d2d3039ce6 | ||
| 
						 | 
					16e85a7b79 | ||
| 
						 | 
					4ae1c01e13 | ||
| 
						 | 
					8807afc074 | ||
| 
						 | 
					a4e13e07d5 | ||
| 
						 | 
					6067d59336 | ||
| 
						 | 
					e14aecee66 | ||
| 
						 | 
					0e4c3e3427 | ||
| 
						 | 
					da5c563426 | ||
| 
						 | 
					b9f5d8b1c5 | ||
| 
						 | 
					5ea7b562a2 | ||
| 
						 | 
					8450970b80 | ||
| 
						 | 
					14d4cff530 | ||
| 
						 | 
					88ac659d86 | ||
| 
						 | 
					43fdbf27b9 | ||
| 
						 | 
					1e33f8e868 | ||
| 
						 | 
					a6e30857df | ||
| 
						 | 
					563f24edb0 | ||
| 
						 | 
					a89f6d5da2 | ||
| 
						 | 
					5b2e91986a | ||
| 
						 | 
					fbc5056817 | ||
| 
						 | 
					b7cafed040 | ||
| 
						 | 
					b6ebd34b30 | ||
| 
						 | 
					74c2765159 | ||
| 
						 | 
					62c7fdadba | ||
| 
						 | 
					372c66e684 | ||
| 
						 | 
					a2fab5bcaf | ||
| 
						 | 
					2e4f41571c | ||
| 
						 | 
					8799a6dbfd | ||
| 
						 | 
					e655087027 | ||
| 
						 | 
					46bd2a4090 | ||
| 
						 | 
					f3b8a8aef3 | ||
| 
						 | 
					ee0c917e95 | ||
| 
						 | 
					375aedd340 | ||
| 
						 | 
					95397a7710 | ||
| 
						 | 
					7af8a52d27 | ||
| 
						 | 
					326a8093c9 | ||
| 
						 | 
					9f0e159205 | ||
| 
						 | 
					2fda101b44 | ||
| 
						 | 
					e6e1e4f9dd | ||
| 
						 | 
					70591265e5 | ||
| 
						 | 
					ed1d477a45 | ||
| 
						 | 
					cd58f636d3 | ||
| 
						 | 
					3152f2233f | ||
| 
						 | 
					0c147a895c | ||
| 
						 | 
					cf80710ef1 | ||
| 
						 | 
					fc929ab984 | ||
| 
						 | 
					145a8817dc | 
@@ -24,6 +24,8 @@
 | 
			
		||||
#include <test/jtx/multisign.h>
 | 
			
		||||
#include <test/jtx/xchain_bridge.h>
 | 
			
		||||
 | 
			
		||||
#include <xrpld/app/tx/apply.h>
 | 
			
		||||
 | 
			
		||||
#include <xrpl/beast/unit_test.h>
 | 
			
		||||
#include <xrpl/json/json_value.h>
 | 
			
		||||
#include <xrpl/protocol/AccountID.h>
 | 
			
		||||
@@ -2027,6 +2029,370 @@ class LedgerEntry_test : public beast::unit_test::suite
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Test the ledger entry types that don't take parameters
 | 
			
		||||
    void
 | 
			
		||||
    testLedgerEntryFixed()
 | 
			
		||||
    {
 | 
			
		||||
        using namespace test::jtx;
 | 
			
		||||
 | 
			
		||||
        Account const alice{"alice"};
 | 
			
		||||
        Account const bob{"bob"};
 | 
			
		||||
 | 
			
		||||
        Env env{*this, envconfig([](auto cfg) {
 | 
			
		||||
                    cfg->START_UP = Config::FRESH;
 | 
			
		||||
                    return cfg;
 | 
			
		||||
                })};
 | 
			
		||||
 | 
			
		||||
        env.close();
 | 
			
		||||
 | 
			
		||||
        /** Verifies that the RPC result has the expected data
 | 
			
		||||
         *
 | 
			
		||||
         * @param good: Indicates that the request should have succeeded
 | 
			
		||||
         *   and returned a ledger object of `expectedType` type.
 | 
			
		||||
         * @param jv: The RPC result Json value
 | 
			
		||||
         * @param expectedType: The type that the ledger object should
 | 
			
		||||
         *   have if "good".
 | 
			
		||||
         * @param expectedError: Optional. The expected error if not
 | 
			
		||||
         *   good. Defaults to "entryNotFound".
 | 
			
		||||
         */
 | 
			
		||||
        auto checkResult =
 | 
			
		||||
            [&](bool good,
 | 
			
		||||
                Json::Value const& jv,
 | 
			
		||||
                Json::StaticString const& expectedType,
 | 
			
		||||
                std::optional<std::string> const& expectedError = {}) {
 | 
			
		||||
                if (good)
 | 
			
		||||
                {
 | 
			
		||||
                    BEAST_EXPECTS(
 | 
			
		||||
                        jv.isObject() && jv.isMember(jss::result) &&
 | 
			
		||||
                            !jv[jss::result].isMember(jss::error) &&
 | 
			
		||||
                            jv[jss::result].isMember(jss::node) &&
 | 
			
		||||
                            jv[jss::result][jss::node].isMember(
 | 
			
		||||
                                sfLedgerEntryType.jsonName) &&
 | 
			
		||||
                            jv[jss::result][jss::node]
 | 
			
		||||
                              [sfLedgerEntryType.jsonName] == expectedType,
 | 
			
		||||
                        to_string(jv));
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    BEAST_EXPECTS(
 | 
			
		||||
                        jv.isObject() && jv.isMember(jss::result) &&
 | 
			
		||||
                            jv[jss::result].isMember(jss::error) &&
 | 
			
		||||
                            !jv[jss::result].isMember(jss::node) &&
 | 
			
		||||
                            jv[jss::result][jss::error] ==
 | 
			
		||||
                                expectedError.value_or("entryNotFound"),
 | 
			
		||||
                        to_string(jv));
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
        /** Runs a series of tests for a given fixed-position ledger
 | 
			
		||||
         * entry.
 | 
			
		||||
         *
 | 
			
		||||
         * @param field: The Json request field to use.
 | 
			
		||||
         * @param expectedType: The type that the ledger object should
 | 
			
		||||
         *   have if "good".
 | 
			
		||||
         * @param expectedKey: The keylet of the fixed object.
 | 
			
		||||
         * @param good: Indicates whether the object is expected to
 | 
			
		||||
         *   exist.
 | 
			
		||||
         */
 | 
			
		||||
        auto test = [&](Json::StaticString const& field,
 | 
			
		||||
                        Json::StaticString const& expectedType,
 | 
			
		||||
                        Keylet const& expectedKey,
 | 
			
		||||
                        bool good) {
 | 
			
		||||
            testcase << "ledger_entry " << expectedType.c_str()
 | 
			
		||||
                     << (good ? "" : " not") << " found";
 | 
			
		||||
 | 
			
		||||
            auto const hexKey = strHex(expectedKey.key);
 | 
			
		||||
 | 
			
		||||
            // Test bad values
 | 
			
		||||
            // "field":null
 | 
			
		||||
            Json::Value params;
 | 
			
		||||
            params[jss::ledger_index] = jss::validated;
 | 
			
		||||
            params[field] = Json::nullValue;
 | 
			
		||||
            auto jv = env.rpc("json", "ledger_entry", to_string(params));
 | 
			
		||||
            checkResult(false, jv, expectedType, "malformedRequest");
 | 
			
		||||
            BEAST_EXPECT(!jv[jss::result].isMember(jss::index));
 | 
			
		||||
 | 
			
		||||
            // "field":"string"
 | 
			
		||||
            params.clear();
 | 
			
		||||
            params[jss::ledger_index] = jss::validated;
 | 
			
		||||
            params[field] = "arbitrary string";
 | 
			
		||||
            jv = env.rpc("json", "ledger_entry", to_string(params));
 | 
			
		||||
            checkResult(false, jv, expectedType, "malformedRequest");
 | 
			
		||||
            BEAST_EXPECT(!jv[jss::result].isMember(jss::index));
 | 
			
		||||
 | 
			
		||||
            // "field":false
 | 
			
		||||
            params.clear();
 | 
			
		||||
            params[jss::ledger_index] = jss::validated;
 | 
			
		||||
            params[field] = false;
 | 
			
		||||
            jv = env.rpc("json", "ledger_entry", to_string(params));
 | 
			
		||||
            checkResult(false, jv, expectedType, "invalidParams");
 | 
			
		||||
            BEAST_EXPECT(!jv[jss::result].isMember(jss::index));
 | 
			
		||||
 | 
			
		||||
            {
 | 
			
		||||
                // "field":[incorrect index hash]
 | 
			
		||||
                auto const badKey = strHex(expectedKey.key + uint256{1});
 | 
			
		||||
                params.clear();
 | 
			
		||||
                params[jss::ledger_index] = jss::validated;
 | 
			
		||||
                params[field] = badKey;
 | 
			
		||||
                jv = env.rpc("json", "ledger_entry", to_string(params));
 | 
			
		||||
                checkResult(false, jv, expectedType, "entryNotFound");
 | 
			
		||||
                BEAST_EXPECTS(
 | 
			
		||||
                    jv[jss::result][jss::index] == badKey, to_string(jv));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // "index":"field" using API 2
 | 
			
		||||
            params.clear();
 | 
			
		||||
            params[jss::ledger_index] = jss::validated;
 | 
			
		||||
            params[jss::index] = field;
 | 
			
		||||
            params[jss::api_version] = 2;
 | 
			
		||||
            jv = env.rpc("json", "ledger_entry", to_string(params));
 | 
			
		||||
            checkResult(false, jv, expectedType, "malformedRequest");
 | 
			
		||||
            BEAST_EXPECT(!jv[jss::result].isMember(jss::index));
 | 
			
		||||
 | 
			
		||||
            // Test good values
 | 
			
		||||
            // Use the "field":true notation
 | 
			
		||||
            params.clear();
 | 
			
		||||
            params[jss::ledger_index] = jss::validated;
 | 
			
		||||
            params[field] = true;
 | 
			
		||||
            jv = env.rpc("json", "ledger_entry", to_string(params));
 | 
			
		||||
            // Index will always be returned for valid parameters.
 | 
			
		||||
            std::string const pdIdx = jv[jss::result][jss::index].asString();
 | 
			
		||||
            BEAST_EXPECTS(hexKey == pdIdx, to_string(jv));
 | 
			
		||||
            checkResult(good, jv, expectedType);
 | 
			
		||||
 | 
			
		||||
            // "field":"[index hash]"
 | 
			
		||||
            params.clear();
 | 
			
		||||
            params[jss::ledger_index] = jss::validated;
 | 
			
		||||
            params[field] = hexKey;
 | 
			
		||||
            jv = env.rpc("json", "ledger_entry", to_string(params));
 | 
			
		||||
            checkResult(good, jv, expectedType);
 | 
			
		||||
            BEAST_EXPECT(jv[jss::result][jss::index].asString() == hexKey);
 | 
			
		||||
 | 
			
		||||
            // Use the "index":"field" notation with API 3
 | 
			
		||||
            params.clear();
 | 
			
		||||
            params[jss::ledger_index] = jss::validated;
 | 
			
		||||
            params[jss::index] = field;
 | 
			
		||||
            params[jss::api_version] = 3;
 | 
			
		||||
            jv = env.rpc("json", "ledger_entry", to_string(params));
 | 
			
		||||
            // Index is correct either way
 | 
			
		||||
            BEAST_EXPECT(jv[jss::result][jss::index].asString() == hexKey);
 | 
			
		||||
            checkResult(good, jv, expectedType);
 | 
			
		||||
 | 
			
		||||
            // Use the "index":"[index hash]" notation
 | 
			
		||||
            params.clear();
 | 
			
		||||
            params[jss::ledger_index] = jss::validated;
 | 
			
		||||
            params[jss::index] = pdIdx;
 | 
			
		||||
            jv = env.rpc("json", "ledger_entry", to_string(params));
 | 
			
		||||
            // Index is correct either way
 | 
			
		||||
            BEAST_EXPECT(jv[jss::result][jss::index].asString() == hexKey);
 | 
			
		||||
            checkResult(good, jv, expectedType);
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        test(jss::amendments, jss::Amendments, keylet::amendments(), true);
 | 
			
		||||
        test(jss::fee, jss::FeeSettings, keylet::fees(), true);
 | 
			
		||||
        // There won't be an nunl
 | 
			
		||||
        test(jss::nunl, jss::NegativeUNL, keylet::negativeUNL(), false);
 | 
			
		||||
        // Can only get the short skip list this way
 | 
			
		||||
        test(jss::hashes, jss::LedgerHashes, keylet::skip(), true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void
 | 
			
		||||
    testLedgerEntryHashes()
 | 
			
		||||
    {
 | 
			
		||||
        using namespace test::jtx;
 | 
			
		||||
 | 
			
		||||
        Account const alice{"alice"};
 | 
			
		||||
        Account const bob{"bob"};
 | 
			
		||||
 | 
			
		||||
        Env env{*this, envconfig([](auto cfg) {
 | 
			
		||||
                    cfg->START_UP = Config::FRESH;
 | 
			
		||||
                    return cfg;
 | 
			
		||||
                })};
 | 
			
		||||
 | 
			
		||||
        env.close();
 | 
			
		||||
 | 
			
		||||
        /** Verifies that the RPC result has the expected data
 | 
			
		||||
         *
 | 
			
		||||
         * @param good: Indicates that the request should have succeeded
 | 
			
		||||
         *   and returned a ledger object of `expectedType` type.
 | 
			
		||||
         * @param jv: The RPC result Json value
 | 
			
		||||
         * @param expectedCount: The number of Hashes expected in the
 | 
			
		||||
         *   object if "good".
 | 
			
		||||
         * @param expectedError: Optional. The expected error if not
 | 
			
		||||
         *   good. Defaults to "entryNotFound".
 | 
			
		||||
         */
 | 
			
		||||
        auto checkResult =
 | 
			
		||||
            [&](bool good,
 | 
			
		||||
                Json::Value const& jv,
 | 
			
		||||
                int expectedCount,
 | 
			
		||||
                std::optional<std::string> const& expectedError = {}) {
 | 
			
		||||
                if (good)
 | 
			
		||||
                {
 | 
			
		||||
                    BEAST_EXPECTS(
 | 
			
		||||
                        jv.isObject() && jv.isMember(jss::result) &&
 | 
			
		||||
                            !jv[jss::result].isMember(jss::error) &&
 | 
			
		||||
                            jv[jss::result].isMember(jss::node) &&
 | 
			
		||||
                            jv[jss::result][jss::node].isMember(
 | 
			
		||||
                                sfLedgerEntryType.jsonName) &&
 | 
			
		||||
                            jv[jss::result][jss::node]
 | 
			
		||||
                              [sfLedgerEntryType.jsonName] == jss::LedgerHashes,
 | 
			
		||||
                        to_string(jv));
 | 
			
		||||
                    BEAST_EXPECTS(
 | 
			
		||||
                        jv[jss::result].isMember(jss::node) &&
 | 
			
		||||
                            jv[jss::result][jss::node].isMember("Hashes") &&
 | 
			
		||||
                            jv[jss::result][jss::node]["Hashes"].size() ==
 | 
			
		||||
                                expectedCount,
 | 
			
		||||
                        to_string(jv[jss::result][jss::node]["Hashes"].size()));
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    BEAST_EXPECTS(
 | 
			
		||||
                        jv.isObject() && jv.isMember(jss::result) &&
 | 
			
		||||
                            jv[jss::result].isMember(jss::error) &&
 | 
			
		||||
                            !jv[jss::result].isMember(jss::node) &&
 | 
			
		||||
                            jv[jss::result][jss::error] ==
 | 
			
		||||
                                expectedError.value_or("entryNotFound"),
 | 
			
		||||
                        to_string(jv));
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
        /** Runs a series of tests for a given ledger index.
 | 
			
		||||
         *
 | 
			
		||||
         * @param ledger: The ledger index value of the "hashes" request
 | 
			
		||||
         *   parameter. May not necessarily be a number.
 | 
			
		||||
         * @param expectedKey: The expected keylet of the object.
 | 
			
		||||
         * @param good: Indicates whether the object is expected to
 | 
			
		||||
         *   exist.
 | 
			
		||||
         * @param expectedCount: The number of Hashes expected in the
 | 
			
		||||
         *   object if "good".
 | 
			
		||||
         */
 | 
			
		||||
        auto test = [&](Json::Value ledger,
 | 
			
		||||
                        Keylet const& expectedKey,
 | 
			
		||||
                        bool good,
 | 
			
		||||
                        int expectedCount = 0) {
 | 
			
		||||
            testcase << "ledger_entry LedgerHashes: seq: "
 | 
			
		||||
                     << env.current()->info().seq
 | 
			
		||||
                     << " \"hashes\":" << to_string(ledger)
 | 
			
		||||
                     << (good ? "" : " not") << " found";
 | 
			
		||||
 | 
			
		||||
            auto const hexKey = strHex(expectedKey.key);
 | 
			
		||||
 | 
			
		||||
            // Test bad values
 | 
			
		||||
            // "hashes":null
 | 
			
		||||
            Json::Value params;
 | 
			
		||||
            params[jss::ledger_index] = jss::validated;
 | 
			
		||||
            params[jss::hashes] = Json::nullValue;
 | 
			
		||||
            auto jv = env.rpc("json", "ledger_entry", to_string(params));
 | 
			
		||||
            checkResult(false, jv, 0, "malformedRequest");
 | 
			
		||||
            BEAST_EXPECT(!jv[jss::result].isMember(jss::index));
 | 
			
		||||
 | 
			
		||||
            // "hashes":"non-uint string"
 | 
			
		||||
            params.clear();
 | 
			
		||||
            params[jss::ledger_index] = jss::validated;
 | 
			
		||||
            params[jss::hashes] = "arbitrary string";
 | 
			
		||||
            jv = env.rpc("json", "ledger_entry", to_string(params));
 | 
			
		||||
            checkResult(false, jv, 0, "malformedRequest");
 | 
			
		||||
            BEAST_EXPECT(!jv[jss::result].isMember(jss::index));
 | 
			
		||||
 | 
			
		||||
            // "hashes":"uint string" is invalid, too
 | 
			
		||||
            params.clear();
 | 
			
		||||
            params[jss::ledger_index] = jss::validated;
 | 
			
		||||
            params[jss::hashes] = "10";
 | 
			
		||||
            jv = env.rpc("json", "ledger_entry", to_string(params));
 | 
			
		||||
            checkResult(false, jv, 0, "malformedRequest");
 | 
			
		||||
            BEAST_EXPECT(!jv[jss::result].isMember(jss::index));
 | 
			
		||||
 | 
			
		||||
            // "hashes":false
 | 
			
		||||
            params.clear();
 | 
			
		||||
            params[jss::ledger_index] = jss::validated;
 | 
			
		||||
            params[jss::hashes] = false;
 | 
			
		||||
            jv = env.rpc("json", "ledger_entry", to_string(params));
 | 
			
		||||
            checkResult(false, jv, 0, "invalidParams");
 | 
			
		||||
            BEAST_EXPECT(!jv[jss::result].isMember(jss::index));
 | 
			
		||||
 | 
			
		||||
            // "hashes":-1
 | 
			
		||||
            params.clear();
 | 
			
		||||
            params[jss::ledger_index] = jss::validated;
 | 
			
		||||
            params[jss::hashes] = -1;
 | 
			
		||||
            jv = env.rpc("json", "ledger_entry", to_string(params));
 | 
			
		||||
            checkResult(false, jv, 0, "internal");
 | 
			
		||||
            BEAST_EXPECT(!jv[jss::result].isMember(jss::index));
 | 
			
		||||
 | 
			
		||||
            // "hashes":[incorrect index hash]
 | 
			
		||||
            {
 | 
			
		||||
                auto const badKey = strHex(expectedKey.key + uint256{1});
 | 
			
		||||
                params.clear();
 | 
			
		||||
                params[jss::ledger_index] = jss::validated;
 | 
			
		||||
                params[jss::hashes] = badKey;
 | 
			
		||||
                jv = env.rpc("json", "ledger_entry", to_string(params));
 | 
			
		||||
                checkResult(false, jv, 0, "entryNotFound");
 | 
			
		||||
                BEAST_EXPECT(jv[jss::result][jss::index] == badKey);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Test good values
 | 
			
		||||
            // Use the "hashes":ledger notation
 | 
			
		||||
            params.clear();
 | 
			
		||||
            params[jss::ledger_index] = jss::validated;
 | 
			
		||||
            params[jss::hashes] = ledger;
 | 
			
		||||
            jv = env.rpc("json", "ledger_entry", to_string(params));
 | 
			
		||||
            checkResult(good, jv, expectedCount);
 | 
			
		||||
            // Index will always be returned for valid parameters.
 | 
			
		||||
            std::string const pdIdx = jv[jss::result][jss::index].asString();
 | 
			
		||||
            BEAST_EXPECTS(hexKey == pdIdx, strHex(pdIdx));
 | 
			
		||||
 | 
			
		||||
            // "hashes":"[index hash]"
 | 
			
		||||
            params.clear();
 | 
			
		||||
            params[jss::ledger_index] = jss::validated;
 | 
			
		||||
            params[jss::hashes] = hexKey;
 | 
			
		||||
            jv = env.rpc("json", "ledger_entry", to_string(params));
 | 
			
		||||
            checkResult(good, jv, expectedCount);
 | 
			
		||||
            // Index is correct either way
 | 
			
		||||
            BEAST_EXPECTS(
 | 
			
		||||
                hexKey == jv[jss::result][jss::index].asString(),
 | 
			
		||||
                strHex(jv[jss::result][jss::index].asString()));
 | 
			
		||||
 | 
			
		||||
            // Use the "index":"[index hash]" notation
 | 
			
		||||
            params.clear();
 | 
			
		||||
            params[jss::ledger_index] = jss::validated;
 | 
			
		||||
            params[jss::index] = hexKey;
 | 
			
		||||
            jv = env.rpc("json", "ledger_entry", to_string(params));
 | 
			
		||||
            checkResult(good, jv, expectedCount);
 | 
			
		||||
            // Index is correct either way
 | 
			
		||||
            BEAST_EXPECTS(
 | 
			
		||||
                hexKey == jv[jss::result][jss::index].asString(),
 | 
			
		||||
                strHex(jv[jss::result][jss::index].asString()));
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        // short skip list
 | 
			
		||||
        test(true, keylet::skip(), true, 2);
 | 
			
		||||
        // long skip list at index 0
 | 
			
		||||
        test(1, keylet::skip(1), false);
 | 
			
		||||
        // long skip list at index 1
 | 
			
		||||
        test(1 << 17, keylet::skip(1 << 17), false);
 | 
			
		||||
 | 
			
		||||
        // Close more ledgers, but stop short of the flag ledger
 | 
			
		||||
        for (auto i = env.current()->seq(); i <= 250; ++i)
 | 
			
		||||
            env.close();
 | 
			
		||||
 | 
			
		||||
        // short skip list
 | 
			
		||||
        test(true, keylet::skip(), true, 249);
 | 
			
		||||
        // long skip list at index 0
 | 
			
		||||
        test(1, keylet::skip(1), false);
 | 
			
		||||
        // long skip list at index 1
 | 
			
		||||
        test(1 << 17, keylet::skip(1 << 17), false);
 | 
			
		||||
 | 
			
		||||
        // Close a flag ledger so the first "long" skip list is created
 | 
			
		||||
        for (auto i = env.current()->seq(); i <= 260; ++i)
 | 
			
		||||
            env.close();
 | 
			
		||||
 | 
			
		||||
        // short skip list
 | 
			
		||||
        test(true, keylet::skip(), true, 256);
 | 
			
		||||
        // long skip list at index 0
 | 
			
		||||
        test(1, keylet::skip(1), true, 1);
 | 
			
		||||
        // long skip list at index 1
 | 
			
		||||
        test(1 << 17, keylet::skip(1 << 17), false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void
 | 
			
		||||
    testLedgerEntryCLI()
 | 
			
		||||
    {
 | 
			
		||||
@@ -2076,6 +2442,8 @@ public:
 | 
			
		||||
        testOracleLedgerEntry();
 | 
			
		||||
        testLedgerEntryMPT();
 | 
			
		||||
        testLedgerEntryPermissionedDomain();
 | 
			
		||||
        testLedgerEntryFixed();
 | 
			
		||||
        testLedgerEntryHashes();
 | 
			
		||||
        testLedgerEntryCLI();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -39,6 +39,32 @@
 | 
			
		||||
 | 
			
		||||
namespace ripple {
 | 
			
		||||
 | 
			
		||||
using FunctionType = std::function<Expected<uint256, Json::Value>(
 | 
			
		||||
    Json::Value const&,
 | 
			
		||||
    Json::StaticString const,
 | 
			
		||||
    unsigned apiVersion)>;
 | 
			
		||||
 | 
			
		||||
static Expected<uint256, Json::Value>
 | 
			
		||||
parseFixed(
 | 
			
		||||
    Keylet const& keylet,
 | 
			
		||||
    Json::Value const& params,
 | 
			
		||||
    Json::StaticString const& fieldName,
 | 
			
		||||
    unsigned apiVersion);
 | 
			
		||||
 | 
			
		||||
// Helper function to return FunctionType for objects that have a fixed
 | 
			
		||||
// location. That is, they don't take parameters to compute the index.
 | 
			
		||||
// e.g. amendments, fees, negative UNL, etc.
 | 
			
		||||
static FunctionType
 | 
			
		||||
fixed(Keylet const& keylet)
 | 
			
		||||
{
 | 
			
		||||
    return [&keylet](
 | 
			
		||||
               Json::Value const& params,
 | 
			
		||||
               Json::StaticString const fieldName,
 | 
			
		||||
               unsigned apiVersion) -> Expected<uint256, Json::Value> {
 | 
			
		||||
        return parseFixed(keylet, params, fieldName, apiVersion);
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Expected<uint256, Json::Value>
 | 
			
		||||
parseObjectID(
 | 
			
		||||
    Json::Value const& params,
 | 
			
		||||
@@ -54,13 +80,33 @@ parseObjectID(
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Expected<uint256, Json::Value>
 | 
			
		||||
parseIndex(Json::Value const& params, Json::StaticString const fieldName)
 | 
			
		||||
parseIndex(
 | 
			
		||||
    Json::Value const& params,
 | 
			
		||||
    Json::StaticString const fieldName,
 | 
			
		||||
    unsigned apiVersion)
 | 
			
		||||
{
 | 
			
		||||
    if (apiVersion > 2u && params.isString())
 | 
			
		||||
    {
 | 
			
		||||
        std::string const index = params.asString();
 | 
			
		||||
        if (index == jss::amendments.c_str())
 | 
			
		||||
            return keylet::amendments().key;
 | 
			
		||||
        if (index == jss::fee.c_str())
 | 
			
		||||
            return keylet::fees().key;
 | 
			
		||||
        if (index == jss::nunl)
 | 
			
		||||
            return keylet::negativeUNL().key;
 | 
			
		||||
        if (index == jss::hashes)
 | 
			
		||||
            // Note this only finds the "short" skip list. Use "hashes":index to
 | 
			
		||||
            // get the long list.
 | 
			
		||||
            return keylet::skip().key;
 | 
			
		||||
    }
 | 
			
		||||
    return parseObjectID(params, fieldName, "hex string");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Expected<uint256, Json::Value>
 | 
			
		||||
parseAccountRoot(Json::Value const& params, Json::StaticString const fieldName)
 | 
			
		||||
parseAccountRoot(
 | 
			
		||||
    Json::Value const& params,
 | 
			
		||||
    Json::StaticString const fieldName,
 | 
			
		||||
    unsigned apiVersion)
 | 
			
		||||
{
 | 
			
		||||
    if (auto const account = LedgerEntryHelpers::parse<AccountID>(params))
 | 
			
		||||
    {
 | 
			
		||||
@@ -71,14 +117,13 @@ parseAccountRoot(Json::Value const& params, Json::StaticString const fieldName)
 | 
			
		||||
        "malformedAddress", fieldName, "AccountID");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Expected<uint256, Json::Value>
 | 
			
		||||
parseAmendments(Json::Value const& params, Json::StaticString const fieldName)
 | 
			
		||||
{
 | 
			
		||||
    return parseObjectID(params, fieldName, "hex string");
 | 
			
		||||
}
 | 
			
		||||
auto const parseAmendments = fixed(keylet::amendments());
 | 
			
		||||
 | 
			
		||||
static Expected<uint256, Json::Value>
 | 
			
		||||
parseAMM(Json::Value const& params, Json::StaticString const fieldName)
 | 
			
		||||
parseAMM(
 | 
			
		||||
    Json::Value const& params,
 | 
			
		||||
    Json::StaticString const fieldName,
 | 
			
		||||
    unsigned apiVersion)
 | 
			
		||||
{
 | 
			
		||||
    if (!params.isObject())
 | 
			
		||||
    {
 | 
			
		||||
@@ -105,7 +150,10 @@ parseAMM(Json::Value const& params, Json::StaticString const fieldName)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Expected<uint256, Json::Value>
 | 
			
		||||
parseBridge(Json::Value const& params, Json::StaticString const fieldName)
 | 
			
		||||
parseBridge(
 | 
			
		||||
    Json::Value const& params,
 | 
			
		||||
    Json::StaticString const fieldName,
 | 
			
		||||
    unsigned apiVersion)
 | 
			
		||||
{
 | 
			
		||||
    if (!params.isMember(jss::bridge))
 | 
			
		||||
    {
 | 
			
		||||
@@ -136,13 +184,19 @@ parseBridge(Json::Value const& params, Json::StaticString const fieldName)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Expected<uint256, Json::Value>
 | 
			
		||||
parseCheck(Json::Value const& params, Json::StaticString const fieldName)
 | 
			
		||||
parseCheck(
 | 
			
		||||
    Json::Value const& params,
 | 
			
		||||
    Json::StaticString const fieldName,
 | 
			
		||||
    unsigned apiVersion)
 | 
			
		||||
{
 | 
			
		||||
    return parseObjectID(params, fieldName, "hex string");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Expected<uint256, Json::Value>
 | 
			
		||||
parseCredential(Json::Value const& cred, Json::StaticString const fieldName)
 | 
			
		||||
parseCredential(
 | 
			
		||||
    Json::Value const& cred,
 | 
			
		||||
    Json::StaticString const fieldName,
 | 
			
		||||
    unsigned apiVersion)
 | 
			
		||||
{
 | 
			
		||||
    if (!cred.isObject())
 | 
			
		||||
    {
 | 
			
		||||
@@ -173,7 +227,10 @@ parseCredential(Json::Value const& cred, Json::StaticString const fieldName)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Expected<uint256, Json::Value>
 | 
			
		||||
parseDelegate(Json::Value const& params, Json::StaticString const fieldName)
 | 
			
		||||
parseDelegate(
 | 
			
		||||
    Json::Value const& params,
 | 
			
		||||
    Json::StaticString const fieldName,
 | 
			
		||||
    unsigned apiVersion)
 | 
			
		||||
{
 | 
			
		||||
    if (!params.isObject())
 | 
			
		||||
    {
 | 
			
		||||
@@ -241,7 +298,10 @@ parseAuthorizeCredentials(Json::Value const& jv)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Expected<uint256, Json::Value>
 | 
			
		||||
parseDepositPreauth(Json::Value const& dp, Json::StaticString const fieldName)
 | 
			
		||||
parseDepositPreauth(
 | 
			
		||||
    Json::Value const& dp,
 | 
			
		||||
    Json::StaticString const fieldName,
 | 
			
		||||
    unsigned apiVersion)
 | 
			
		||||
{
 | 
			
		||||
    if (!dp.isObject())
 | 
			
		||||
    {
 | 
			
		||||
@@ -301,7 +361,10 @@ parseDepositPreauth(Json::Value const& dp, Json::StaticString const fieldName)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Expected<uint256, Json::Value>
 | 
			
		||||
parseDID(Json::Value const& params, Json::StaticString const fieldName)
 | 
			
		||||
parseDID(
 | 
			
		||||
    Json::Value const& params,
 | 
			
		||||
    Json::StaticString const fieldName,
 | 
			
		||||
    unsigned apiVersion)
 | 
			
		||||
{
 | 
			
		||||
    auto const account = LedgerEntryHelpers::parse<AccountID>(params);
 | 
			
		||||
    if (!account)
 | 
			
		||||
@@ -316,7 +379,8 @@ parseDID(Json::Value const& params, Json::StaticString const fieldName)
 | 
			
		||||
static Expected<uint256, Json::Value>
 | 
			
		||||
parseDirectoryNode(
 | 
			
		||||
    Json::Value const& params,
 | 
			
		||||
    Json::StaticString const fieldName)
 | 
			
		||||
    Json::StaticString const fieldName,
 | 
			
		||||
    unsigned apiVersion)
 | 
			
		||||
{
 | 
			
		||||
    if (!params.isObject())
 | 
			
		||||
    {
 | 
			
		||||
@@ -369,7 +433,10 @@ parseDirectoryNode(
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Expected<uint256, Json::Value>
 | 
			
		||||
parseEscrow(Json::Value const& params, Json::StaticString const fieldName)
 | 
			
		||||
parseEscrow(
 | 
			
		||||
    Json::Value const& params,
 | 
			
		||||
    Json::StaticString const fieldName,
 | 
			
		||||
    unsigned apiVersion)
 | 
			
		||||
{
 | 
			
		||||
    if (!params.isObject())
 | 
			
		||||
    {
 | 
			
		||||
@@ -388,20 +455,53 @@ parseEscrow(Json::Value const& params, Json::StaticString const fieldName)
 | 
			
		||||
    return keylet::escrow(*id, *seq).key;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
auto const parseFeeSettings = fixed(keylet::fees());
 | 
			
		||||
 | 
			
		||||
static Expected<uint256, Json::Value>
 | 
			
		||||
parseFeeSettings(Json::Value const& params, Json::StaticString const fieldName)
 | 
			
		||||
parseFixed(
 | 
			
		||||
    Keylet const& keylet,
 | 
			
		||||
    Json::Value const& params,
 | 
			
		||||
    Json::StaticString const& fieldName,
 | 
			
		||||
    unsigned apiVersion)
 | 
			
		||||
{
 | 
			
		||||
    return parseObjectID(params, fieldName, "hex string");
 | 
			
		||||
    if (!params.isBool())
 | 
			
		||||
    {
 | 
			
		||||
        return parseObjectID(params, fieldName, "hex string");
 | 
			
		||||
    }
 | 
			
		||||
    if (!params.asBool())
 | 
			
		||||
    {
 | 
			
		||||
        return LedgerEntryHelpers::invalidFieldError(
 | 
			
		||||
            "invalidParams", fieldName, "true");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return keylet.key;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Expected<uint256, Json::Value>
 | 
			
		||||
parseLedgerHashes(Json::Value const& params, Json::StaticString const fieldName)
 | 
			
		||||
parseLedgerHashes(
 | 
			
		||||
    Json::Value const& params,
 | 
			
		||||
    Json::StaticString const fieldName,
 | 
			
		||||
    unsigned apiVersion)
 | 
			
		||||
{
 | 
			
		||||
    return parseObjectID(params, fieldName, "hex string");
 | 
			
		||||
    if (params.isUInt() || params.isInt())
 | 
			
		||||
    {
 | 
			
		||||
        // If the index doesn't parse as a UInt, throw
 | 
			
		||||
        auto const index = params.asUInt();
 | 
			
		||||
 | 
			
		||||
        // Return the "long" skip list for the given ledger index.
 | 
			
		||||
        auto const keylet = keylet::skip(index);
 | 
			
		||||
        return keylet.key;
 | 
			
		||||
    }
 | 
			
		||||
    // Return the key in `params` or the "short" skip list, which contains
 | 
			
		||||
    // hashes since the last flag ledger.
 | 
			
		||||
    return parseFixed(keylet::skip(), params, fieldName, apiVersion);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Expected<uint256, Json::Value>
 | 
			
		||||
parseMPToken(Json::Value const& params, Json::StaticString const fieldName)
 | 
			
		||||
parseMPToken(
 | 
			
		||||
    Json::Value const& params,
 | 
			
		||||
    Json::StaticString const fieldName,
 | 
			
		||||
    unsigned apiVersion)
 | 
			
		||||
{
 | 
			
		||||
    if (!params.isObject())
 | 
			
		||||
    {
 | 
			
		||||
@@ -424,7 +524,8 @@ parseMPToken(Json::Value const& params, Json::StaticString const fieldName)
 | 
			
		||||
static Expected<uint256, Json::Value>
 | 
			
		||||
parseMPTokenIssuance(
 | 
			
		||||
    Json::Value const& params,
 | 
			
		||||
    Json::StaticString const fieldName)
 | 
			
		||||
    Json::StaticString const fieldName,
 | 
			
		||||
    unsigned apiVersion)
 | 
			
		||||
{
 | 
			
		||||
    auto const mptIssuanceID = LedgerEntryHelpers::parse<uint192>(params);
 | 
			
		||||
    if (!mptIssuanceID)
 | 
			
		||||
@@ -435,25 +536,30 @@ parseMPTokenIssuance(
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Expected<uint256, Json::Value>
 | 
			
		||||
parseNFTokenOffer(Json::Value const& params, Json::StaticString const fieldName)
 | 
			
		||||
parseNFTokenOffer(
 | 
			
		||||
    Json::Value const& params,
 | 
			
		||||
    Json::StaticString const fieldName,
 | 
			
		||||
    unsigned apiVersion)
 | 
			
		||||
{
 | 
			
		||||
    return parseObjectID(params, fieldName, "hex string");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Expected<uint256, Json::Value>
 | 
			
		||||
parseNFTokenPage(Json::Value const& params, Json::StaticString const fieldName)
 | 
			
		||||
parseNFTokenPage(
 | 
			
		||||
    Json::Value const& params,
 | 
			
		||||
    Json::StaticString const fieldName,
 | 
			
		||||
    unsigned apiVersion)
 | 
			
		||||
{
 | 
			
		||||
    return parseObjectID(params, fieldName, "hex string");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Expected<uint256, Json::Value>
 | 
			
		||||
parseNegativeUNL(Json::Value const& params, Json::StaticString const fieldName)
 | 
			
		||||
{
 | 
			
		||||
    return parseObjectID(params, fieldName, "hex string");
 | 
			
		||||
}
 | 
			
		||||
auto const parseNegativeUNL = fixed(keylet::negativeUNL());
 | 
			
		||||
 | 
			
		||||
static Expected<uint256, Json::Value>
 | 
			
		||||
parseOffer(Json::Value const& params, Json::StaticString const fieldName)
 | 
			
		||||
parseOffer(
 | 
			
		||||
    Json::Value const& params,
 | 
			
		||||
    Json::StaticString const fieldName,
 | 
			
		||||
    unsigned apiVersion)
 | 
			
		||||
{
 | 
			
		||||
    if (!params.isObject())
 | 
			
		||||
    {
 | 
			
		||||
@@ -474,7 +580,10 @@ parseOffer(Json::Value const& params, Json::StaticString const fieldName)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Expected<uint256, Json::Value>
 | 
			
		||||
parseOracle(Json::Value const& params, Json::StaticString const fieldName)
 | 
			
		||||
parseOracle(
 | 
			
		||||
    Json::Value const& params,
 | 
			
		||||
    Json::StaticString const fieldName,
 | 
			
		||||
    unsigned apiVersion)
 | 
			
		||||
{
 | 
			
		||||
    if (!params.isObject())
 | 
			
		||||
    {
 | 
			
		||||
@@ -495,7 +604,10 @@ parseOracle(Json::Value const& params, Json::StaticString const fieldName)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Expected<uint256, Json::Value>
 | 
			
		||||
parsePayChannel(Json::Value const& params, Json::StaticString const fieldName)
 | 
			
		||||
parsePayChannel(
 | 
			
		||||
    Json::Value const& params,
 | 
			
		||||
    Json::StaticString const fieldName,
 | 
			
		||||
    unsigned apiVersion)
 | 
			
		||||
{
 | 
			
		||||
    return parseObjectID(params, fieldName, "hex string");
 | 
			
		||||
}
 | 
			
		||||
@@ -503,7 +615,8 @@ parsePayChannel(Json::Value const& params, Json::StaticString const fieldName)
 | 
			
		||||
static Expected<uint256, Json::Value>
 | 
			
		||||
parsePermissionedDomain(
 | 
			
		||||
    Json::Value const& pd,
 | 
			
		||||
    Json::StaticString const fieldName)
 | 
			
		||||
    Json::StaticString const fieldName,
 | 
			
		||||
    unsigned apiVersion)
 | 
			
		||||
{
 | 
			
		||||
    if (pd.isString())
 | 
			
		||||
    {
 | 
			
		||||
@@ -532,7 +645,8 @@ parsePermissionedDomain(
 | 
			
		||||
static Expected<uint256, Json::Value>
 | 
			
		||||
parseRippleState(
 | 
			
		||||
    Json::Value const& jvRippleState,
 | 
			
		||||
    Json::StaticString const fieldName)
 | 
			
		||||
    Json::StaticString const fieldName,
 | 
			
		||||
    unsigned apiVersion)
 | 
			
		||||
{
 | 
			
		||||
    Currency uCurrency;
 | 
			
		||||
 | 
			
		||||
@@ -582,13 +696,19 @@ parseRippleState(
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Expected<uint256, Json::Value>
 | 
			
		||||
parseSignerList(Json::Value const& params, Json::StaticString const fieldName)
 | 
			
		||||
parseSignerList(
 | 
			
		||||
    Json::Value const& params,
 | 
			
		||||
    Json::StaticString const fieldName,
 | 
			
		||||
    unsigned apiVersion)
 | 
			
		||||
{
 | 
			
		||||
    return parseObjectID(params, fieldName, "hex string");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Expected<uint256, Json::Value>
 | 
			
		||||
parseTicket(Json::Value const& params, Json::StaticString const fieldName)
 | 
			
		||||
parseTicket(
 | 
			
		||||
    Json::Value const& params,
 | 
			
		||||
    Json::StaticString const fieldName,
 | 
			
		||||
    unsigned apiVersion)
 | 
			
		||||
{
 | 
			
		||||
    if (!params.isObject())
 | 
			
		||||
    {
 | 
			
		||||
@@ -609,7 +729,10 @@ parseTicket(Json::Value const& params, Json::StaticString const fieldName)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Expected<uint256, Json::Value>
 | 
			
		||||
parseVault(Json::Value const& params, Json::StaticString const fieldName)
 | 
			
		||||
parseVault(
 | 
			
		||||
    Json::Value const& params,
 | 
			
		||||
    Json::StaticString const fieldName,
 | 
			
		||||
    unsigned apiVersion)
 | 
			
		||||
{
 | 
			
		||||
    if (!params.isObject())
 | 
			
		||||
    {
 | 
			
		||||
@@ -632,7 +755,8 @@ parseVault(Json::Value const& params, Json::StaticString const fieldName)
 | 
			
		||||
static Expected<uint256, Json::Value>
 | 
			
		||||
parseXChainOwnedClaimID(
 | 
			
		||||
    Json::Value const& claim_id,
 | 
			
		||||
    Json::StaticString const fieldName)
 | 
			
		||||
    Json::StaticString const fieldName,
 | 
			
		||||
    unsigned apiVersion)
 | 
			
		||||
{
 | 
			
		||||
    if (!claim_id.isObject())
 | 
			
		||||
    {
 | 
			
		||||
@@ -657,7 +781,8 @@ parseXChainOwnedClaimID(
 | 
			
		||||
static Expected<uint256, Json::Value>
 | 
			
		||||
parseXChainOwnedCreateAccountClaimID(
 | 
			
		||||
    Json::Value const& claim_id,
 | 
			
		||||
    Json::StaticString const fieldName)
 | 
			
		||||
    Json::StaticString const fieldName,
 | 
			
		||||
    unsigned apiVersion)
 | 
			
		||||
{
 | 
			
		||||
    if (!claim_id.isObject())
 | 
			
		||||
    {
 | 
			
		||||
@@ -681,10 +806,6 @@ parseXChainOwnedCreateAccountClaimID(
 | 
			
		||||
    return keylet.key;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
using FunctionType = Expected<uint256, Json::Value> (*)(
 | 
			
		||||
    Json::Value const&,
 | 
			
		||||
    Json::StaticString const);
 | 
			
		||||
 | 
			
		||||
struct LedgerEntry
 | 
			
		||||
{
 | 
			
		||||
    Json::StaticString fieldName;
 | 
			
		||||
@@ -717,7 +838,7 @@ doLedgerEntry(RPC::JsonContext& context)
 | 
			
		||||
        {jss::ripple_state, parseRippleState, ltRIPPLE_STATE},
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    auto hasMoreThanOneMember = [&]() {
 | 
			
		||||
    auto const hasMoreThanOneMember = [&]() {
 | 
			
		||||
        int count = 0;
 | 
			
		||||
 | 
			
		||||
        for (auto const& ledgerEntry : ledgerEntryParsers)
 | 
			
		||||
@@ -761,8 +882,8 @@ doLedgerEntry(RPC::JsonContext& context)
 | 
			
		||||
                Json::Value const& params = ledgerEntry.fieldName == jss::bridge
 | 
			
		||||
                    ? context.params
 | 
			
		||||
                    : context.params[ledgerEntry.fieldName];
 | 
			
		||||
                auto const result =
 | 
			
		||||
                    ledgerEntry.parseFunction(params, ledgerEntry.fieldName);
 | 
			
		||||
                auto const result = ledgerEntry.parseFunction(
 | 
			
		||||
                    params, ledgerEntry.fieldName, context.apiVersion);
 | 
			
		||||
                if (!result)
 | 
			
		||||
                    return result.error();
 | 
			
		||||
 | 
			
		||||
@@ -793,9 +914,13 @@ doLedgerEntry(RPC::JsonContext& context)
 | 
			
		||||
            throw;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Return the computed index regardless of whether the node exists.
 | 
			
		||||
    jvResult[jss::index] = to_string(uNodeIndex);
 | 
			
		||||
 | 
			
		||||
    if (uNodeIndex.isZero())
 | 
			
		||||
    {
 | 
			
		||||
        return RPC::make_error(rpcENTRY_NOT_FOUND);
 | 
			
		||||
        RPC::inject_error(rpcENTRY_NOT_FOUND, jvResult);
 | 
			
		||||
        return jvResult;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto const sleNode = lpLedger->read(keylet::unchecked(uNodeIndex));
 | 
			
		||||
@@ -807,12 +932,14 @@ doLedgerEntry(RPC::JsonContext& context)
 | 
			
		||||
    if (!sleNode)
 | 
			
		||||
    {
 | 
			
		||||
        // Not found.
 | 
			
		||||
        return RPC::make_error(rpcENTRY_NOT_FOUND);
 | 
			
		||||
        RPC::inject_error(rpcENTRY_NOT_FOUND, jvResult);
 | 
			
		||||
        return jvResult;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((expectedType != ltANY) && (expectedType != sleNode->getType()))
 | 
			
		||||
    {
 | 
			
		||||
        return RPC::make_error(rpcUNEXPECTED_LEDGER_TYPE);
 | 
			
		||||
        RPC::inject_error(rpcUNEXPECTED_LEDGER_TYPE, jvResult);
 | 
			
		||||
        return jvResult;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (bNodeBinary)
 | 
			
		||||
@@ -822,12 +949,10 @@ doLedgerEntry(RPC::JsonContext& context)
 | 
			
		||||
        sleNode->add(s);
 | 
			
		||||
 | 
			
		||||
        jvResult[jss::node_binary] = strHex(s.peekData());
 | 
			
		||||
        jvResult[jss::index] = to_string(uNodeIndex);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        jvResult[jss::node] = sleNode->getJson(JsonOptions::none);
 | 
			
		||||
        jvResult[jss::index] = to_string(uNodeIndex);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return jvResult;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user