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