xrpld
Loading...
Searching...
No Matches
CTID.h
1#pragma once
2
3#include <boost/regex.hpp>
4
5#include <cstdint>
6#include <iomanip>
7#include <ios>
8#include <optional>
9#include <sstream>
10#include <string>
11#include <string_view>
12#include <tuple>
13
14namespace xrpl::rpc {
15
16// CTID stands for Concise Transaction ID.
17//
18// The CTID comes from XLS-15d: Concise Transaction Identifier #34
19//
20// https://github.com/XRPLF/XRPL-Standards/discussions/34
21//
22// The Concise Transaction ID provides a way to identify a transaction
23// that includes which network the transaction was submitted to.
24
35inline std::optional<std::string>
36encodeCTID(uint32_t ledgerSeq, uint32_t txnIndex, uint32_t networkID) noexcept
37{
38 static constexpr uint32_t kMaxLedgerSeq = 0x0FFF'FFFF;
39 static constexpr uint32_t kMaxTxnIndex = 0xFFFF;
40 static constexpr uint32_t kMaxNetworkId = 0xFFFF;
41
42 if (ledgerSeq > kMaxLedgerSeq || txnIndex > kMaxTxnIndex || networkID > kMaxNetworkId)
43 return std::nullopt;
44
45 uint64_t const ctidValue = ((0xC000'0000ULL + static_cast<uint64_t>(ledgerSeq)) << 32) |
46 ((static_cast<uint64_t>(txnIndex) << 16) | networkID);
47
48 std::stringstream buffer;
49 buffer << std::hex << std::uppercase << std::setfill('0') << std::setw(16) << ctidValue;
50 return buffer.str();
51}
52
61template <typename T>
63decodeCTID(T const ctid) noexcept
64{
65 uint64_t ctidValue = 0;
66
67 if constexpr (
70 {
71 std::string const ctidString(ctid);
72
73 if (ctidString.size() != 16)
74 return std::nullopt;
75
76 static boost::regex const kHexRegex("^[0-9A-Fa-f]{16}$");
77 if (!boost::regex_match(ctidString, kHexRegex))
78 return std::nullopt;
79
80 try
81 {
82 ctidValue = std::stoull(ctidString, nullptr, 16);
83 }
84 // LCOV_EXCL_START
85 catch (...)
86 {
87 // should be impossible to hit given the length/regex check
88 return std::nullopt;
89 }
90 // LCOV_EXCL_STOP
91 }
92 else if constexpr (std::is_integral_v<T>)
93 {
94 ctidValue = static_cast<uint64_t>(ctid);
95 }
96 else
97 {
98 return std::nullopt;
99 }
100
101 // Validate CTID prefix.
102 static constexpr uint64_t kCtidPrefixMask = 0xF000'0000'0000'0000ULL;
103 static constexpr uint64_t kCtidPrefix = 0xC000'0000'0000'0000ULL;
104 if ((ctidValue & kCtidPrefixMask) != kCtidPrefix)
105 return std::nullopt;
106
107 auto const ledgerSeq = static_cast<uint32_t>((ctidValue >> 32) & 0x0FFF'FFFF);
108 auto const txnIndex = static_cast<uint16_t>((ctidValue >> 16) & 0xFFFF);
109 auto const networkID = static_cast<uint16_t>(ctidValue & 0xFFFF);
110
111 return std::make_tuple(ledgerSeq, txnIndex, networkID);
112}
113
114} // namespace xrpl::rpc
T hex(T... args)
T is_integral_v
T is_same_v
T make_tuple(T... args)
API version numbers used in later API versions.
Definition ApiVersion.h:36
std::optional< std::string > encodeCTID(uint32_t ledgerSeq, uint32_t txnIndex, uint32_t networkID) noexcept
Encodes ledger sequence, transaction index, and network ID into a CTID string.
Definition CTID.h:36
std::optional< std::tuple< uint32_t, uint16_t, uint16_t > > decodeCTID(T const ctid) noexcept
Decodes a CTID string or integer into its component parts.
Definition CTID.h:63
T setfill(T... args)
T setw(T... args)
T size(T... args)
T stoull(T... args)
T str(T... args)
T uppercase(T... args)