rippled
Loading...
Searching...
No Matches
CTID.h
1#ifndef XRPL_RPC_CTID_H_INCLUDED
2#define XRPL_RPC_CTID_H_INCLUDED
3
4#include <boost/regex.hpp>
5
6#include <optional>
7#include <regex>
8#include <sstream>
9
10namespace ripple {
11
12namespace RPC {
13
14// CTID stands for Concise Transaction ID.
15//
16// The CTID comes from XLS-15d: Concise Transaction Identifier #34
17//
18// https://github.com/XRPLF/XRPL-Standards/discussions/34
19//
20// The Concise Transaction ID provides a way to identify a transaction
21// that includes which network the transaction was submitted to.
22
34encodeCTID(uint32_t ledgerSeq, uint32_t txnIndex, uint32_t networkID) noexcept
35{
36 constexpr uint32_t maxLedgerSeq = 0x0FFF'FFFF;
37 constexpr uint32_t maxTxnIndex = 0xFFFF;
38 constexpr uint32_t maxNetworkID = 0xFFFF;
39
40 if (ledgerSeq > maxLedgerSeq || txnIndex > maxTxnIndex ||
41 networkID > maxNetworkID)
42 return std::nullopt;
43
44 uint64_t ctidValue =
45 ((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)
50 << ctidValue;
51 return buffer.str();
52}
53
62template <typename T>
64decodeCTID(T const ctid) noexcept
65{
66 uint64_t ctidValue = 0;
67
68 if constexpr (
71 {
72 std::string const ctidString(ctid);
73
74 if (ctidString.size() != 16)
75 return std::nullopt;
76
77 static boost::regex const hexRegex("^[0-9A-Fa-f]{16}$");
78 if (!boost::regex_match(ctidString, hexRegex))
79 return std::nullopt;
80
81 try
82 {
83 ctidValue = std::stoull(ctidString, nullptr, 16);
84 }
85 // LCOV_EXCL_START
86 catch (...)
87 {
88 // should be impossible to hit given the length/regex check
89 return std::nullopt;
90 }
91 // LCOV_EXCL_STOP
92 }
93 else if constexpr (std::is_integral_v<T>)
94 {
95 ctidValue = static_cast<uint64_t>(ctid);
96 }
97 else
98 {
99 return std::nullopt;
100 }
101
102 // Validate CTID prefix.
103 constexpr uint64_t ctidPrefixMask = 0xF000'0000'0000'0000ULL;
104 constexpr uint64_t ctidPrefix = 0xC000'0000'0000'0000ULL;
105 if ((ctidValue & ctidPrefixMask) != ctidPrefix)
106 return std::nullopt;
107
108 uint32_t ledgerSeq = static_cast<uint32_t>((ctidValue >> 32) & 0x0FFF'FFFF);
109 uint16_t txnIndex = static_cast<uint16_t>((ctidValue >> 16) & 0xFFFF);
110 uint16_t networkID = static_cast<uint16_t>(ctidValue & 0xFFFF);
111
112 return std::make_tuple(ledgerSeq, txnIndex, networkID);
113}
114
115} // namespace RPC
116} // namespace ripple
117
118#endif
T hex(T... args)
T is_same_v
T make_tuple(T... args)
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:34
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:64
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
T setfill(T... args)
T setw(T... args)
T size(T... args)
T stoull(T... args)
T str(T... args)
T uppercase(T... args)