mirror of
				https://github.com/Xahau/xahaud.git
				synced 2025-11-04 10:45:50 +00:00 
			
		
		
		
	CTID sync rippled (#114)
* clang-format * add `'` seperator to hex constants fix bad seperator clang-format * remove impossible validation add parenthesis * pre-increment `it` * add leading 0 * use boost_regex * add leading 0 * `const` after declare variable * clang-format * add extra check on std::optional * move guard * add test * update test to match * rename `txnIDfromIndex` -> `txnIdFromIndex` * update test to match guard * fix test naming --------- Co-authored-by: Richard Holland <richard.holland@starstone.co.nz>
This commit is contained in:
		@@ -294,7 +294,7 @@ public:
 | 
			
		||||
 | 
			
		||||
    // Iff a txn exists at the specified ledger and offset then return its txnid
 | 
			
		||||
    std::optional<uint256>
 | 
			
		||||
    txnIDfromIndex(uint32_t ledgerSeq, uint32_t txnIndex);
 | 
			
		||||
    txnIdFromIndex(uint32_t ledgerSeq, uint32_t txnIndex);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void
 | 
			
		||||
 
 | 
			
		||||
@@ -2374,7 +2374,7 @@ LedgerMaster::minSqlSeq()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::optional<uint256>
 | 
			
		||||
LedgerMaster::txnIDfromIndex(uint32_t ledgerSeq, uint32_t txnIndex)
 | 
			
		||||
LedgerMaster::txnIdFromIndex(uint32_t ledgerSeq, uint32_t txnIndex)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t first = 0, last = 0;
 | 
			
		||||
 | 
			
		||||
@@ -2385,7 +2385,7 @@ LedgerMaster::txnIDfromIndex(uint32_t ledgerSeq, uint32_t txnIndex)
 | 
			
		||||
    if (!lgr || lgr->txs.empty())
 | 
			
		||||
        return {};
 | 
			
		||||
 | 
			
		||||
    for (auto it = lgr->txs.begin(); it != lgr->txs.end(); it++)
 | 
			
		||||
    for (auto it = lgr->txs.begin(); it != lgr->txs.end(); ++it)
 | 
			
		||||
        if (it->first && it->second &&
 | 
			
		||||
            it->second->isFieldPresent(sfTransactionIndex) &&
 | 
			
		||||
            it->second->getFieldU32(sfTransactionIndex) == txnIndex)
 | 
			
		||||
 
 | 
			
		||||
@@ -21,6 +21,7 @@
 | 
			
		||||
#define RIPPLE_RPC_CTID_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include <boost/algorithm/string/predicate.hpp>
 | 
			
		||||
#include <boost/regex.hpp>
 | 
			
		||||
#include <optional>
 | 
			
		||||
#include <regex>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
@@ -35,11 +36,11 @@ encodeCTID(
 | 
			
		||||
    uint16_t txn_index,
 | 
			
		||||
    uint16_t network_id) noexcept
 | 
			
		||||
{
 | 
			
		||||
    if (ledger_seq > 0xFFFFFFF)
 | 
			
		||||
    if (ledger_seq > 0x0FFF'FFFF)
 | 
			
		||||
        return {};
 | 
			
		||||
 | 
			
		||||
    uint64_t ctidValue =
 | 
			
		||||
        ((0xC0000000ULL + static_cast<uint64_t>(ledger_seq)) << 32) +
 | 
			
		||||
        ((0xC000'0000ULL + static_cast<uint64_t>(ledger_seq)) << 32) +
 | 
			
		||||
        (static_cast<uint64_t>(txn_index) << 16) + network_id;
 | 
			
		||||
 | 
			
		||||
    std::stringstream buffer;
 | 
			
		||||
@@ -57,12 +58,12 @@ decodeCTID(const T ctid) noexcept
 | 
			
		||||
        std::is_same_v<T, std::string> || std::is_same_v<T, char*> ||
 | 
			
		||||
        std::is_same_v<T, const char*> || std::is_same_v<T, std::string_view>)
 | 
			
		||||
    {
 | 
			
		||||
        const std::string ctidString(ctid);
 | 
			
		||||
        std::string const ctidString(ctid);
 | 
			
		||||
 | 
			
		||||
        if (ctidString.length() != 16)
 | 
			
		||||
            return {};
 | 
			
		||||
 | 
			
		||||
        if (!std::regex_match(ctidString, std::regex("^[0-9A-F]+$")))
 | 
			
		||||
        if (!boost::regex_match(ctidString, boost::regex("^[0-9A-F]+$")))
 | 
			
		||||
            return {};
 | 
			
		||||
 | 
			
		||||
        ctidValue = std::stoull(ctidString, nullptr, 16);
 | 
			
		||||
@@ -72,11 +73,10 @@ decodeCTID(const T ctid) noexcept
 | 
			
		||||
    else
 | 
			
		||||
        return {};
 | 
			
		||||
 | 
			
		||||
    if (ctidValue > 0xFFFFFFFFFFFFFFFFULL ||
 | 
			
		||||
        (ctidValue & 0xF000000000000000ULL) != 0xC000000000000000ULL)
 | 
			
		||||
    if ((ctidValue & 0xF000'0000'0000'0000ULL) != 0xC000'0000'0000'0000ULL)
 | 
			
		||||
        return {};
 | 
			
		||||
 | 
			
		||||
    uint32_t ledger_seq = (ctidValue >> 32) & 0xFFFFFFFUL;
 | 
			
		||||
    uint32_t ledger_seq = (ctidValue >> 32) & 0xFFFF'FFFUL;
 | 
			
		||||
    uint16_t txn_index = (ctidValue >> 16) & 0xFFFFU;
 | 
			
		||||
    uint16_t network_id = ctidValue & 0xFFFFU;
 | 
			
		||||
    return {{ledger_seq, txn_index, network_id}};
 | 
			
		||||
 
 | 
			
		||||
@@ -25,10 +25,10 @@
 | 
			
		||||
#include <ripple/net/RPCErr.h>
 | 
			
		||||
#include <ripple/protocol/ErrorCodes.h>
 | 
			
		||||
#include <ripple/protocol/jss.h>
 | 
			
		||||
#include <ripple/rpc/CTID.h>
 | 
			
		||||
#include <ripple/rpc/Context.h>
 | 
			
		||||
#include <ripple/rpc/DeliveredAmount.h>
 | 
			
		||||
#include <ripple/rpc/GRPCHandlers.h>
 | 
			
		||||
#include <ripple/rpc/CTID.h>
 | 
			
		||||
#include <ripple/rpc/impl/RPCHelpers.h>
 | 
			
		||||
#include <charconv>
 | 
			
		||||
#include <regex>
 | 
			
		||||
@@ -208,7 +208,7 @@ doTxHelp(RPC::Context& context, TxArgs args)
 | 
			
		||||
 | 
			
		||||
    if (args.ctid)
 | 
			
		||||
    {
 | 
			
		||||
        args.hash = context.app.getLedgerMaster().txnIDfromIndex(
 | 
			
		||||
        args.hash = context.app.getLedgerMaster().txnIdFromIndex(
 | 
			
		||||
            args.ctid->first, args.ctid->second);
 | 
			
		||||
 | 
			
		||||
        if (args.hash)
 | 
			
		||||
@@ -231,6 +231,9 @@ doTxHelp(RPC::Context& context, TxArgs args)
 | 
			
		||||
        return {result, rpcTXN_NOT_FOUND};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!args.hash)
 | 
			
		||||
        return {result, rpcTXN_NOT_FOUND};
 | 
			
		||||
 | 
			
		||||
    auto [txn, meta] = std::get<TxPair>(v);
 | 
			
		||||
 | 
			
		||||
    if (ec == rpcDB_DESERIALIZATION)
 | 
			
		||||
@@ -274,8 +277,9 @@ doTxHelp(RPC::Context& context, TxArgs args)
 | 
			
		||||
        uint32_t txnIdx = meta->getAsObject().getFieldU32(sfTransactionIndex);
 | 
			
		||||
        uint32_t netID = context.app.config().NETWORK_ID;
 | 
			
		||||
 | 
			
		||||
        if (txnIdx <= 0xFFFFU && netID < 0xFFFFU && lgrSeq < 0xFFFFFFFUL)
 | 
			
		||||
            result.ctid = RPC::encodeCTID(lgrSeq, (uint16_t)txnIdx, (uint16_t)netID);
 | 
			
		||||
        if (txnIdx <= 0xFFFFU && netID < 0xFFFFU && lgrSeq < 0x0FFF'FFFFUL)
 | 
			
		||||
            result.ctid =
 | 
			
		||||
                RPC::encodeCTID(lgrSeq, (uint16_t)txnIdx, (uint16_t)netID);
 | 
			
		||||
        */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -38,7 +38,7 @@ class LedgerMaster_test : public beast::unit_test::suite
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void
 | 
			
		||||
    testTxnIDfromIndex(FeatureBitset features)
 | 
			
		||||
    testTxnIdFromIndex(FeatureBitset features)
 | 
			
		||||
    {
 | 
			
		||||
        testcase("tx_id_from_index");
 | 
			
		||||
 | 
			
		||||
@@ -72,39 +72,49 @@ class LedgerMaster_test : public beast::unit_test::suite
 | 
			
		||||
            std::uint32_t ledgerSeq = -1;
 | 
			
		||||
            std::uint32_t txnIndex = 0;
 | 
			
		||||
            auto result =
 | 
			
		||||
                env.app().getLedgerMaster().txnIDfromIndex(ledgerSeq, txnIndex);
 | 
			
		||||
                env.app().getLedgerMaster().txnIdFromIndex(ledgerSeq, txnIndex);
 | 
			
		||||
            BEAST_EXPECT(!result);
 | 
			
		||||
        }
 | 
			
		||||
        // test not in ledger
 | 
			
		||||
        {
 | 
			
		||||
            uint32_t txnIndex = metas[0]->getFieldU32(sfTransactionIndex);
 | 
			
		||||
            auto result =
 | 
			
		||||
                env.app().getLedgerMaster().txnIDfromIndex(0, txnIndex);
 | 
			
		||||
                env.app().getLedgerMaster().txnIdFromIndex(0, txnIndex);
 | 
			
		||||
            BEAST_EXPECT(!result);
 | 
			
		||||
        }
 | 
			
		||||
        // test empty ledger
 | 
			
		||||
        {
 | 
			
		||||
            auto result =
 | 
			
		||||
                env.app().getLedgerMaster().txnIDfromIndex(endLegSeq, 0);
 | 
			
		||||
                env.app().getLedgerMaster().txnIdFromIndex(endLegSeq, 0);
 | 
			
		||||
            BEAST_EXPECT(!result);
 | 
			
		||||
        }
 | 
			
		||||
        // ended without result
 | 
			
		||||
        {
 | 
			
		||||
            uint32_t txnIndex = metas[0]->getFieldU32(sfTransactionIndex);
 | 
			
		||||
            auto result = env.app().getLedgerMaster().txnIDfromIndex(
 | 
			
		||||
            auto result = env.app().getLedgerMaster().txnIdFromIndex(
 | 
			
		||||
                endLegSeq + 1, txnIndex);
 | 
			
		||||
            BEAST_EXPECT(!result);
 | 
			
		||||
        }
 | 
			
		||||
        // success
 | 
			
		||||
        // success (first tx)
 | 
			
		||||
        {
 | 
			
		||||
            uint32_t txnIndex = metas[0]->getFieldU32(sfTransactionIndex);
 | 
			
		||||
            auto result = env.app().getLedgerMaster().txnIDfromIndex(
 | 
			
		||||
            auto result = env.app().getLedgerMaster().txnIdFromIndex(
 | 
			
		||||
                startLegSeq, txnIndex);
 | 
			
		||||
            BEAST_EXPECT(
 | 
			
		||||
                *result ==
 | 
			
		||||
                uint256("277F4FD89C20B92457FEF05FF63F6405563AD0563C73D967A29727"
 | 
			
		||||
                        "72679ADC65"));
 | 
			
		||||
        }
 | 
			
		||||
        // success (second tx)
 | 
			
		||||
        {
 | 
			
		||||
            uint32_t txnIndex = metas[1]->getFieldU32(sfTransactionIndex);
 | 
			
		||||
            auto result = env.app().getLedgerMaster().txnIdFromIndex(
 | 
			
		||||
                startLegSeq + 1, txnIndex);
 | 
			
		||||
            BEAST_EXPECT(
 | 
			
		||||
                *result ==
 | 
			
		||||
                uint256("293DF7335EBBAF4420D52E70ABF470EB4C5792CAEA2F91F76193C2"
 | 
			
		||||
                        "819F538FDE"));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
@@ -119,7 +129,7 @@ public:
 | 
			
		||||
    void
 | 
			
		||||
    testWithFeats(FeatureBitset features)
 | 
			
		||||
    {
 | 
			
		||||
        testTxnIDfromIndex(features);
 | 
			
		||||
        testTxnIdFromIndex(features);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -133,7 +133,11 @@ public:
 | 
			
		||||
                auto jt = env.jtnofill(jvn, alice);
 | 
			
		||||
                Serializer s;
 | 
			
		||||
                jt.stx->add(s);
 | 
			
		||||
                BEAST_EXPECT(env.rpc("submit", strHex(s.slice()))[jss::result][jss::engine_result] == "telREQUIRES_NETWORK_ID");
 | 
			
		||||
                BEAST_EXPECT(
 | 
			
		||||
                    env.rpc(
 | 
			
		||||
                        "submit",
 | 
			
		||||
                        strHex(s.slice()))[jss::result][jss::engine_result] ==
 | 
			
		||||
                    "telREQUIRES_NETWORK_ID");
 | 
			
		||||
                env.close();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -351,7 +351,7 @@ class Transaction_test : public beast::unit_test::suite
 | 
			
		||||
        auto const tx = env.jt(noop(alice), seq(env.seq(alice))).stx;
 | 
			
		||||
        auto const ctid =
 | 
			
		||||
            *RPC::encodeCTID(endLegSeq, tx->getSeqProxy().value(), netID);
 | 
			
		||||
        for (int deltaEndSeq = 0; deltaEndSeq < 3; ++deltaEndSeq)
 | 
			
		||||
        for (int deltaEndSeq = 0; deltaEndSeq < 2; ++deltaEndSeq)
 | 
			
		||||
        {
 | 
			
		||||
            auto const result = env.rpc(
 | 
			
		||||
                COMMAND,
 | 
			
		||||
@@ -367,7 +367,7 @@ class Transaction_test : public beast::unit_test::suite
 | 
			
		||||
            if (deltaEndSeq)
 | 
			
		||||
                BEAST_EXPECT(!result[jss::result][jss::searched_all].asBool());
 | 
			
		||||
            else
 | 
			
		||||
                BEAST_EXPECT(result[jss::result][jss::searched_all].asBool());
 | 
			
		||||
                BEAST_EXPECT(!result[jss::result][jss::searched_all].asBool());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Find transactions outside of provided range.
 | 
			
		||||
@@ -435,7 +435,7 @@ class Transaction_test : public beast::unit_test::suite
 | 
			
		||||
                result[jss::result][jss::status] == jss::error &&
 | 
			
		||||
                result[jss::result][jss::error] == NOT_FOUND);
 | 
			
		||||
 | 
			
		||||
            BEAST_EXPECT(result[jss::result][jss::searched_all].asBool());
 | 
			
		||||
            BEAST_EXPECT(!result[jss::result][jss::searched_all].asBool());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Provide range without providing the `binary`
 | 
			
		||||
@@ -552,7 +552,7 @@ class Transaction_test : public beast::unit_test::suite
 | 
			
		||||
        // Test case 1: Valid input values
 | 
			
		||||
        auto const expected11 = std::optional<std::string>("CFFFFFFFFFFFFFFF");
 | 
			
		||||
        BEAST_EXPECT(
 | 
			
		||||
            RPC::encodeCTID(0xFFFFFFFUL, 0xFFFFU, 0xFFFFU) == expected11);
 | 
			
		||||
            RPC::encodeCTID(0x0FFF'FFFFUL, 0xFFFFU, 0xFFFFU) == expected11);
 | 
			
		||||
        auto const expected12 = std::optional<std::string>("C000000000000000");
 | 
			
		||||
        BEAST_EXPECT(RPC::encodeCTID(0, 0, 0) == expected12);
 | 
			
		||||
        auto const expected13 = std::optional<std::string>("C000000100020003");
 | 
			
		||||
@@ -561,21 +561,22 @@ class Transaction_test : public beast::unit_test::suite
 | 
			
		||||
        BEAST_EXPECT(RPC::encodeCTID(13249191UL, 12911U, 65535U) == expected14);
 | 
			
		||||
 | 
			
		||||
        // Test case 2: ledger_seq greater than 0xFFFFFFF
 | 
			
		||||
        BEAST_EXPECT(!RPC::encodeCTID(0x10000000UL, 0xFFFFU, 0xFFFFU));
 | 
			
		||||
        BEAST_EXPECT(!RPC::encodeCTID(0x1000'0000UL, 0xFFFFU, 0xFFFFU));
 | 
			
		||||
 | 
			
		||||
        // Test case 3: txn_index greater than 0xFFFF
 | 
			
		||||
        // this test case is impossible in c++ due to the type, left in for
 | 
			
		||||
        // completeness
 | 
			
		||||
        auto const expected3 = std::optional<std::string>("CFFFFFFF0000FFFF");
 | 
			
		||||
        BEAST_EXPECT(
 | 
			
		||||
            RPC::encodeCTID(0xFFFFFFF, (uint16_t)0x10000, 0xFFFF) == expected3);
 | 
			
		||||
            RPC::encodeCTID(0x0FFF'FFFF, (uint16_t)0x10000, 0xFFFF) ==
 | 
			
		||||
            expected3);
 | 
			
		||||
 | 
			
		||||
        // Test case 4: network_id greater than 0xFFFF
 | 
			
		||||
        // this test case is impossible in c++ due to the type, left in for
 | 
			
		||||
        // completeness
 | 
			
		||||
        auto const expected4 = std::optional<std::string>("CFFFFFFFFFFF0000");
 | 
			
		||||
        BEAST_EXPECT(
 | 
			
		||||
            RPC::encodeCTID(0xFFFFFFFUL, 0xFFFFU, (uint16_t)0x10000U) ==
 | 
			
		||||
            RPC::encodeCTID(0x0FFF'FFFFUL, 0xFFFFU, (uint16_t)0x1000'0U) ==
 | 
			
		||||
            expected4);
 | 
			
		||||
 | 
			
		||||
        // Test case 5: Valid input values
 | 
			
		||||
@@ -609,24 +610,24 @@ class Transaction_test : public beast::unit_test::suite
 | 
			
		||||
 | 
			
		||||
        // Test case 11: Valid input values
 | 
			
		||||
        BEAST_EXPECT(
 | 
			
		||||
            (RPC::decodeCTID(0xCFFFFFFFFFFFFFFFULL) ==
 | 
			
		||||
            (RPC::decodeCTID(0xCFFF'FFFF'FFFF'FFFFULL) ==
 | 
			
		||||
             std::optional<std::tuple<int32_t, uint16_t, uint16_t>>(
 | 
			
		||||
                 std::make_tuple(0xFFFFFFFUL, 0xFFFFU, 0xFFFFU))));
 | 
			
		||||
                 std::make_tuple(0x0FFF'FFFFUL, 0xFFFFU, 0xFFFFU))));
 | 
			
		||||
        BEAST_EXPECT(
 | 
			
		||||
            (RPC::decodeCTID(0xC000000000000000ULL) ==
 | 
			
		||||
            (RPC::decodeCTID(0xC000'0000'0000'0000ULL) ==
 | 
			
		||||
             std::optional<std::tuple<int32_t, uint16_t, uint16_t>>(
 | 
			
		||||
                 std::make_tuple(0, 0, 0))));
 | 
			
		||||
        BEAST_EXPECT(
 | 
			
		||||
            (RPC::decodeCTID(0xC000000100020003ULL) ==
 | 
			
		||||
            (RPC::decodeCTID(0xC000'0001'0002'0003ULL) ==
 | 
			
		||||
             std::optional<std::tuple<int32_t, uint16_t, uint16_t>>(
 | 
			
		||||
                 std::make_tuple(1U, 2U, 3U))));
 | 
			
		||||
        BEAST_EXPECT(
 | 
			
		||||
            (RPC::decodeCTID(0xC0CA2AA7326FC045ULL) ==
 | 
			
		||||
            (RPC::decodeCTID(0xC0CA'2AA7'326F'C045ULL) ==
 | 
			
		||||
             std::optional<std::tuple<int32_t, uint16_t, uint16_t>>(
 | 
			
		||||
                 std::make_tuple(13249191UL, 12911U, 49221U))));
 | 
			
		||||
                 std::make_tuple(1324'9191UL, 12911U, 49221U))));
 | 
			
		||||
 | 
			
		||||
        // Test case 12: ctid not exactly 16 nibbles
 | 
			
		||||
        BEAST_EXPECT(!RPC::decodeCTID(0xC003FFFFFFFFFFF));
 | 
			
		||||
        BEAST_EXPECT(!RPC::decodeCTID(0xC003'FFFF'FFFF'FFF));
 | 
			
		||||
 | 
			
		||||
        // Test case 13: ctid too large to be a valid CTID value
 | 
			
		||||
        // this test case is not possible in c++ because it would overflow the
 | 
			
		||||
@@ -634,7 +635,7 @@ class Transaction_test : public beast::unit_test::suite
 | 
			
		||||
        // BEAST_EXPECT(!RPC::decodeCTID(0xCFFFFFFFFFFFFFFFFULL));
 | 
			
		||||
 | 
			
		||||
        // Test case 14: ctid doesn't start with a C nibble
 | 
			
		||||
        BEAST_EXPECT(!RPC::decodeCTID(0xFFFFFFFFFFFFFFFFULL));
 | 
			
		||||
        BEAST_EXPECT(!RPC::decodeCTID(0xFFFF'FFFF'FFFF'FFFFULL));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user