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 <stdexcept>
22#include <string>
23#include <type_traits>
24#include <utility>
25
26namespace xrpl {
27
29SHAMapTreeNode::makeTransaction(Slice data, SHAMapHash const& hash, bool hashValid)
30{
31 if (data.size() < kMinShaMapItemBytes)
32 {
34 "Short TXN node: " + std::to_string(data.size()) + " bytes (minimum " +
35 std::to_string(kMinShaMapItemBytes) + " required)");
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: " + std::to_string(s.size()) + " bytes (minimum " +
57 std::to_string(tag.kBytes) + " required for tag)");
58 }
59
60 // FIXME: improve this interface so that the above check isn't needed
61 if (!s.getBitString(tag, s.size() - tag.kBytes))
62 {
64 "Short TXN+MD node: failed to read tag at offset " +
65 std::to_string(s.size() - tag.kBytes));
66 }
67
68 s.chop(tag.kBytes);
69
70 if (s.size() < kMinShaMapItemBytes)
71 {
73 "Short TXN+MD node: " + std::to_string(s.size()) +
74 " bytes after tag removal (minimum " + std::to_string(kMinShaMapItemBytes) +
75 " required)");
76 }
77
78 auto item = makeShamapitem(tag, s.slice());
79
80 if (hashValid)
81 return intr_ptr::makeShared<SHAMapTxPlusMetaLeafNode>(std::move(item), 0, hash);
82
83 return intr_ptr::makeShared<SHAMapTxPlusMetaLeafNode>(std::move(item), 0);
84}
85
87SHAMapTreeNode::makeAccountState(Slice data, SHAMapHash const& hash, bool hashValid)
88{
89 Serializer s(data.data(), data.size());
90
91 uint256 tag;
92
93 if (s.size() < tag.kBytes)
94 {
96 "Short AS node: " + std::to_string(s.size()) + " bytes (minimum " +
97 std::to_string(tag.kBytes) + " required for tag)");
98 }
99
100 // FIXME: improve this interface so that the above check isn't needed
101 if (!s.getBitString(tag, s.size() - tag.kBytes))
102 {
104 "Short AS node: failed to read tag at offset " + std::to_string(s.size() - tag.kBytes));
105 }
106
107 s.chop(tag.kBytes);
108
109 if (tag.isZero())
110 Throw<std::runtime_error>("Invalid AS node");
111
112 if (s.size() < kMinShaMapItemBytes)
113 {
115 "Short AS node: " + std::to_string(s.size()) + " bytes after tag removal (minimum " +
116 std::to_string(kMinShaMapItemBytes) + " required)");
117 }
118
119 auto item = makeShamapitem(tag, s.slice());
120
121 if (hashValid)
122 return intr_ptr::makeShared<SHAMapAccountStateLeafNode>(std::move(item), 0, hash);
123
124 return intr_ptr::makeShared<SHAMapAccountStateLeafNode>(std::move(item), 0);
125}
126
129{
130 if (rawNode.empty())
131 return {};
132
133 auto const type = rawNode[rawNode.size() - 1];
134
135 rawNode.removeSuffix(1);
136
137 bool const hashValid = false;
138 SHAMapHash const hash;
139
140 if (type == kWireTypeTransaction)
141 return makeTransaction(rawNode, hash, hashValid);
142
143 if (type == kWireTypeAccountState)
144 return makeAccountState(rawNode, hash, hashValid);
145
146 if (type == kWireTypeInner)
147 return SHAMapInnerNode::makeFullInner(rawNode, hash, hashValid);
148
149 if (type == kWireTypeCompressedInner)
151
153 return makeTransactionWithMeta(rawNode, hash, hashValid);
154
155 Throw<std::runtime_error>("wire: Unknown type (" + std::to_string(type) + ")");
156}
157
160{
161 if (rawNode.size() < 4)
162 Throw<std::runtime_error>("prefix: short node");
163
164 // FIXME: Use SerialIter::get32?
165 // Extract the prefix
166 auto const type = safeCast<HashPrefix>(
167 (safeCast<std::uint32_t>(rawNode[0]) << 24) + (safeCast<std::uint32_t>(rawNode[1]) << 16) +
168 (safeCast<std::uint32_t>(rawNode[2]) << 8) + (safeCast<std::uint32_t>(rawNode[3])));
169
170 rawNode.removePrefix(4);
171
172 bool const hashValid = true;
173
174 if (type == HashPrefix::TransactionId)
175 return makeTransaction(rawNode, hash, hashValid);
176
177 if (type == HashPrefix::LeafNode)
178 return makeAccountState(rawNode, hash, hashValid);
179
180 if (type == HashPrefix::InnerNode)
181 return SHAMapInnerNode::makeFullInner(rawNode, hash, hashValid);
182
183 if (type == HashPrefix::TxNode)
184 return makeTransactionWithMeta(rawNode, hash, hashValid);
185
187 "prefix: unknown type (" +
189}
190
193{
194 return to_string(id);
195}
196
197} // namespace xrpl
bool isZero() const
Definition base_uint.h:544
static constexpr std::size_t kBytes
Definition base_uint.h:89
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:154
bool chop(int num)
Slice slice() const noexcept
Definition Serializer.h:44
std::size_t size() const noexcept
Definition Serializer.h:50
An immutable linear range of bytes.
Definition Slice.h:26
bool empty() const noexcept
Return true if the byte range is empty.
Definition Slice.h:50
std::size_t size() const noexcept
Returns the number of bytes in the storage.
Definition Slice.h:61
void removePrefix(std::size_t n)
Shrinks the slice by moving its start forward by n characters.
Definition Slice.h:113
void removeSuffix(std::size_t n)
Shrinks the slice by moving its end backward by n characters.
Definition Slice.h:121
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
sha512_half_hasher::result_type sha512Half(Args const &... args)
Returns the SHA512-Half of a series of objects.
Definition digest.h:204
constexpr std::enable_if_t< std::is_integral_v< Dest > &&std::is_integral_v< Src >, Dest > safeCast(Src s) noexcept
Definition safe_cast.h:21
static constexpr unsigned char const kWireTypeTransactionWithMeta
static constexpr unsigned char const kWireTypeCompressedInner
std::string to_string(BaseUInt< Bits, Tag > const &a)
Definition base_uint.h:633
constexpr std::size_t kMinShaMapItemBytes
boost::intrusive_ptr< SHAMapItem > makeShamapitem(uint256 const &tag, Slice data)
Definition SHAMapItem.h:139
static constexpr unsigned char const kWireTypeAccountState
static constexpr unsigned char const kWireTypeTransaction
@ LeafNode
account state
Definition HashPrefix.h:42
@ TransactionId
transaction plus signature to give transaction ID
Definition HashPrefix.h:36
@ InnerNode
inner node in V1 tree
Definition HashPrefix.h:45
@ TxNode
transaction plus metadata
Definition HashPrefix.h:39
static constexpr unsigned char const kWireTypeInner
BaseUInt< 256 > uint256
Definition base_uint.h:562
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
Definition contract.h:49
T to_string(T... args)