xrpld
Loading...
Searching...
No Matches
SHAMapTreeNode.cpp
1#include <xrpl/shamap/SHAMapTreeNode.h>
2
3#include <xrpl/basics/IntrusivePointer.h> // IWYU pragma: keep
4#include <xrpl/basics/IntrusivePointer.ipp> // IWYU pragma: keep
5#include <xrpl/basics/SHAMapHash.h>
6#include <xrpl/basics/Slice.h>
7#include <xrpl/basics/base_uint.h>
8#include <xrpl/basics/contract.h>
9#include <xrpl/basics/safe_cast.h>
10#include <xrpl/protocol/HashPrefix.h>
11#include <xrpl/protocol/Serializer.h>
12#include <xrpl/protocol/digest.h>
13#include <xrpl/shamap/SHAMapAccountStateLeafNode.h>
14#include <xrpl/shamap/SHAMapInnerNode.h>
15#include <xrpl/shamap/SHAMapItem.h>
16#include <xrpl/shamap/SHAMapNodeID.h>
17#include <xrpl/shamap/SHAMapTxLeafNode.h>
18#include <xrpl/shamap/SHAMapTxPlusMetaLeafNode.h>
19
20#include <cstdint>
21#include <format>
22#include <stdexcept>
23#include <string>
24#include <type_traits>
25#include <utility>
26
27namespace xrpl {
28
30SHAMapTreeNode::makeTransaction(Slice data, SHAMapHash const& hash, bool hashValid)
31{
32 if (data.size() < kMinShaMapItemBytes)
33 {
35 "Short TXN node: {} bytes (minimum {} required)", data.size(), kMinShaMapItemBytes));
36 }
37
38 auto item = makeShamapitem(sha512Half(HashPrefix::TransactionId, data), data);
39
40 if (hashValid)
41 return intr_ptr::makeShared<SHAMapTxLeafNode>(std::move(item), 0, hash);
42
43 return intr_ptr::makeShared<SHAMapTxLeafNode>(std::move(item), 0);
44}
45
48{
49 Serializer s(data.data(), data.size());
50
51 UInt256 tag;
52
53 if (s.size() < tag.kBytes)
54 {
56 "Short TXN+MD node: {} bytes (minimum {} required for tag)", s.size(), tag.kBytes));
57 }
58
59 // FIXME: improve this interface so that the above check isn't needed
60 if (!s.getBitString(tag, s.size() - tag.kBytes))
61 {
63 "Short TXN+MD node: failed to read tag at offset {}", s.size() - tag.kBytes));
64 }
65
66 s.chop(tag.kBytes);
67
68 if (s.size() < kMinShaMapItemBytes)
69 {
71 "Short TXN+MD node: {} bytes after tag removal (minimum {} required)",
72 s.size(),
74 }
75
76 auto item = makeShamapitem(tag, s.slice());
77
78 if (hashValid)
79 return intr_ptr::makeShared<SHAMapTxPlusMetaLeafNode>(std::move(item), 0, hash);
80
81 return intr_ptr::makeShared<SHAMapTxPlusMetaLeafNode>(std::move(item), 0);
82}
83
85SHAMapTreeNode::makeAccountState(Slice data, SHAMapHash const& hash, bool hashValid)
86{
87 Serializer s(data.data(), data.size());
88
89 UInt256 tag;
90
91 if (s.size() < tag.kBytes)
92 {
94 "Short AS node: {} bytes (minimum {} required for tag)", s.size(), tag.kBytes));
95 }
96
97 // FIXME: improve this interface so that the above check isn't needed
98 if (!s.getBitString(tag, s.size() - tag.kBytes))
99 {
101 std::format("Short AS node: failed to read tag at offset {}", s.size() - tag.kBytes));
102 }
103
104 s.chop(tag.kBytes);
105
106 if (tag.isZero())
107 Throw<std::runtime_error>("Invalid AS node");
108
109 if (s.size() < kMinShaMapItemBytes)
110 {
112 "Short AS node: {} bytes after tag removal (minimum {} required)",
113 s.size(),
115 }
116
117 auto item = makeShamapitem(tag, s.slice());
118
119 if (hashValid)
120 return intr_ptr::makeShared<SHAMapAccountStateLeafNode>(std::move(item), 0, hash);
121
122 return intr_ptr::makeShared<SHAMapAccountStateLeafNode>(std::move(item), 0);
123}
124
127{
128 if (rawNode.empty())
129 return {};
130
131 auto const type = rawNode[rawNode.size() - 1];
132
133 rawNode.removeSuffix(1);
134
135 bool const hashValid = false;
136 SHAMapHash const hash;
137
138 if (type == kWireTypeTransaction)
139 return makeTransaction(rawNode, hash, hashValid);
140
141 if (type == kWireTypeAccountState)
142 return makeAccountState(rawNode, hash, hashValid);
143
144 if (type == kWireTypeInner)
145 return SHAMapInnerNode::makeFullInner(rawNode, hash, hashValid);
146
147 if (type == kWireTypeCompressedInner)
149
151 return makeTransactionWithMeta(rawNode, hash, hashValid);
152
153 Throw<std::runtime_error>(std::format("wire: Unknown type ({})", type));
154}
155
158{
159 if (rawNode.size() < 4)
160 Throw<std::runtime_error>("prefix: short node");
161
162 // FIXME: Use SerialIter::get32?
163 // Extract the prefix
164 auto const type = safeCast<HashPrefix>(
165 (safeCast<std::uint32_t>(rawNode[0]) << 24) + (safeCast<std::uint32_t>(rawNode[1]) << 16) +
166 (safeCast<std::uint32_t>(rawNode[2]) << 8) + (safeCast<std::uint32_t>(rawNode[3])));
167
168 rawNode.removePrefix(4);
169
170 bool const hashValid = true;
171
172 if (type == HashPrefix::TransactionId)
173 return makeTransaction(rawNode, hash, hashValid);
174
175 if (type == HashPrefix::LeafNode)
176 return makeAccountState(rawNode, hash, hashValid);
177
178 if (type == HashPrefix::InnerNode)
179 return SHAMapInnerNode::makeFullInner(rawNode, hash, hashValid);
180
181 if (type == HashPrefix::TxNode)
182 return makeTransactionWithMeta(rawNode, hash, hashValid);
183
185 "prefix: unknown type ({})", safeCast<std::underlying_type_t<HashPrefix>>(type)));
186}
187
190{
191 return to_string(id);
192}
193
194} // namespace xrpl
bool isZero() const
Definition base_uint.h:562
static constexpr std::size_t kBytes
Definition base_uint.h:100
static SHAMapTreeNodePtr makeCompressedInner(Slice data)
static SHAMapTreeNodePtr makeFullInner(Slice data, SHAMapHash const &hash, bool hashValid)
Identifies a node inside a SHAMap.
static SHAMapTreeNodePtr makeFromPrefix(Slice rawNode, SHAMapHash const &hash)
static SHAMapTreeNodePtr makeFromWire(Slice rawNode)
static SHAMapTreeNodePtr makeAccountState(Slice data, SHAMapHash const &hash, bool hashValid)
static SHAMapTreeNodePtr makeTransaction(Slice data, SHAMapHash const &hash, bool hashValid)
static SHAMapTreeNodePtr makeTransactionWithMeta(Slice data, SHAMapHash const &hash, bool hashValid)
virtual std::string getString(SHAMapNodeID const &) const
bool getBitString(BaseUInt< Bits, Tag > &data, int offset) const
Definition Serializer.h:251
Slice slice() const noexcept
Definition Serializer.h:141
std::size_t size() const noexcept
Definition Serializer.h:147
An immutable linear range of bytes.
Definition Slice.h:28
bool empty() const noexcept
Return true if the byte range is empty.
Definition Slice.h:58
std::size_t size() const noexcept
Returns the number of bytes in the storage.
Definition Slice.h:70
void removePrefix(std::size_t n)
Shrinks the slice by moving its start forward by n characters.
Definition Slice.h:129
void removeSuffix(std::size_t n)
Shrinks the slice by moving its end backward by n characters.
Definition Slice.h:139
T format(T... args)
SharedPtr< T > makeShared(A &&... args)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
intr_ptr::SharedPtr< SHAMapTreeNode > SHAMapTreeNodePtr
static constexpr unsigned char const kWireTypeTransactionWithMeta
constexpr Dest safeCast(Src s) noexcept
Definition safe_cast.h:21
static constexpr unsigned char const kWireTypeCompressedInner
std::string to_string(BaseUInt< Bits, Tag > const &a)
Definition base_uint.h:657
constexpr std::size_t kMinShaMapItemBytes
BaseUInt< 256 > UInt256
Definition base_uint.h:580
boost::intrusive_ptr< SHAMapItem > makeShamapitem(UInt256 const &tag, Slice data)
Definition SHAMapItem.h:148
static constexpr unsigned char const kWireTypeAccountState
static constexpr unsigned char const kWireTypeTransaction
@ LeafNode
account state
Definition HashPrefix.h:49
@ TransactionId
transaction plus signature to give transaction ID
Definition HashPrefix.h:39
@ InnerNode
inner node in V1 tree
Definition HashPrefix.h:54
@ TxNode
transaction plus metadata
Definition HashPrefix.h:44
static constexpr unsigned char const kWireTypeInner
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
Definition contract.h:52
Sha512HalfHasher::result_type sha512Half(Args const &... args)
Returns the SHA512-Half of a series of objects.
Definition digest.h:215