xrpld
Loading...
Searching...
No Matches
CTID.h
1#pragma once
2
3#include <boost/regex.hpp>
4
5#include <optional>
6#include <regex>
7#include <sstream>
8
9namespace xrpl::RPC {
10
11// CTID stands for Concise Transaction ID.
12//
13// The CTID comes from XLS-15d: Concise Transaction Identifier #34
14//
15// https://github.com/XRPLF/XRPL-Standards/discussions/34
16//
17// The Concise Transaction ID provides a way to identify a transaction
18// that includes which network the transaction was submitted to.
19
30inline std::optional<std::string>
31encodeCTID(uint32_t ledgerSeq, uint32_t txnIndex, uint32_t networkID) noexcept
32{
33 static constexpr uint32_t kMaxLedgerSeq = 0x0FFF'FFFF;
34 static constexpr uint32_t kMaxTxnIndex = 0xFFFF;
35 static constexpr uint32_t kMaxNetworkId = 0xFFFF;
36
37 if (ledgerSeq > kMaxLedgerSeq || txnIndex > kMaxTxnIndex || networkID > kMaxNetworkId)
38 return std::nullopt;
39
40 uint64_t const ctidValue = ((0xC000'0000ULL + static_cast<uint64_t>(ledgerSeq)) << 32) |
41 ((static_cast<uint64_t>(txnIndex) << 16) | networkID);
42
43 std::stringstream buffer;
44 buffer << std::hex << std::uppercase << std::setfill('0') << std::setw(16) << ctidValue;
45 return buffer.str();
46}
47
56template <typename T>
58decodeCTID(T const ctid) noexcept
59{
60 uint64_t ctidValue = 0;
61
62 if constexpr (
65 {
66 std::string const ctidString(ctid);
67
68 if (ctidString.size() != 16)
69 return std::nullopt;
70
71 static boost::regex const kHexRegex("^[0-9A-Fa-f]{16}$");
72 if (!boost::regex_match(ctidString, kHexRegex))
73 return std::nullopt;
74
75 try
76 {
77 ctidValue = std::stoull(ctidString, nullptr, 16);
78 }
79 // LCOV_EXCL_START
80 catch (...)
81 {
82 // should be impossible to hit given the length/regex check
83 return std::nullopt;
84 }
85 // LCOV_EXCL_STOP
86 }
87 else if constexpr (std::is_integral_v<T>)
88 {
89 ctidValue = static_cast<uint64_t>(ctid);
90 }
91 else
92 {
93 return std::nullopt;
94 }
95
96 // Validate CTID prefix.
97 static constexpr uint64_t kCtidPrefixMask = 0xF000'0000'0000'0000ULL;
98 static constexpr uint64_t kCtidPrefix = 0xC000'0000'0000'0000ULL;
99 if ((ctidValue & kCtidPrefixMask) != kCtidPrefix)
100 return std::nullopt;
101
102 uint32_t const ledgerSeq = static_cast<uint32_t>((ctidValue >> 32) & 0x0FFF'FFFF);
103 uint16_t const txnIndex = static_cast<uint16_t>((ctidValue >> 16) & 0xFFFF);
104 uint16_t const networkID = static_cast<uint16_t>(ctidValue & 0xFFFF);
105
106 return std::make_tuple(ledgerSeq, txnIndex, networkID);
107}
108
109} // 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:35
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:31
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:58
T setfill(T... args)
T setw(T... args)
T size(T... args)
T stoull(T... args)
T str(T... args)
T uppercase(T... args)