xrpld
Loading...
Searching...
No Matches
SHAMapNodeID.cpp
1#include <xrpl/shamap/SHAMapNodeID.h>
2
3#include <xrpl/basics/base_uint.h>
4#include <xrpl/basics/contract.h>
5#include <xrpl/beast/utility/instrumentation.h>
6#include <xrpl/protocol/Serializer.h>
7#include <xrpl/shamap/SHAMap.h>
8
9#include <cstddef>
10#include <optional>
11#include <stdexcept>
12#include <string>
13
14namespace xrpl {
15
16static uint256 const&
17depthMask(unsigned int depth)
18{
19 static constexpr auto kMaskSize = 65;
20
21 struct MasksT
22 {
23 uint256 entry[kMaskSize];
24
25 MasksT()
26 {
27 uint256 selector;
28 for (int i = 0; i < kMaskSize - 1; i += 2)
29 {
30 entry[i] = selector;
31 *(selector.begin() + (i / 2)) = 0xF0;
32 entry[i + 1] = selector;
33 *(selector.begin() + (i / 2)) = 0xFF;
34 }
35 entry[kMaskSize - 1] = selector;
36 }
37 };
38
39 static MasksT const kMasks;
40 return kMasks.entry[depth];
41}
42
43// canonicalize the hash to a node ID for this depth
44SHAMapNodeID::SHAMapNodeID(unsigned int depth, uint256 const& hash) : id_(hash), depth_(depth)
45{
46 XRPL_ASSERT(
47 depth <= SHAMap::kLeafDepth, "xrpl::SHAMapNodeID::SHAMapNodeID : maximum depth input");
48 XRPL_ASSERT(
49 id_ == (id_ & depthMask(depth)),
50 "xrpl::SHAMapNodeID::SHAMapNodeID : hash and depth inputs do match");
51}
52
55{
56 Serializer s(33);
58 s.add8(depth_);
59 return s.getString();
60}
61
63SHAMapNodeID::getChildNodeID(unsigned int m) const
64{
65 XRPL_ASSERT(
66 m < SHAMap::kBranchFactor, "xrpl::SHAMapNodeID::getChildNodeID : valid branch input");
67
68 // A SHAMap has exactly 65 levels, so nodes must not exceed that
69 // depth; if they do, this breaks the invariant of never allowing
70 // the construction of a SHAMapNodeID at an invalid depth. We assert
71 // to catch this in debug builds.
72 //
73 // We throw (but never assert) if the node is at level 64, since
74 // entries at that depth are leaf nodes and have no children and even
75 // constructing a child node from them would break the above invariant.
76 XRPL_ASSERT(
77 depth_ <= SHAMap::kLeafDepth, "xrpl::SHAMapNodeID::getChildNodeID : maximum leaf depth");
78
80 Throw<std::logic_error>("Request for child node ID of " + to_string(*this));
81
82 if (id_ != (id_ & depthMask(depth_)))
83 Throw<std::logic_error>("Incorrect mask for " + to_string(*this));
84
85 SHAMapNodeID node{depth_ + 1, id_};
86 node.id_.begin()[depth_ / 2] |= ((depth_ & 1) != 0u) ? m : (m << 4);
87 return node;
88}
89
91deserializeSHAMapNodeID(void const* data, std::size_t size)
92{
94
95 if (size == 33)
96 {
97 unsigned int const depth = *(static_cast<unsigned char const*>(data) + 32);
98 if (depth <= SHAMap::kLeafDepth)
99 {
100 auto const id = uint256::fromVoid(data);
101
102 if (id == (id & depthMask(depth)))
103 ret.emplace(depth, id);
104 }
105 }
106
107 return ret;
108}
109
110[[nodiscard]] unsigned int
111selectBranch(SHAMapNodeID const& id, uint256 const& hash)
112{
113 auto const depth = id.getDepth();
114 auto branch = static_cast<unsigned int>(*(hash.begin() + (depth / 2)));
115
116 if ((depth & 1) != 0u)
117 {
118 branch &= 0xf;
119 }
120 else
121 {
122 branch >>= 4;
123 }
124
125 XRPL_ASSERT(branch < SHAMap::kBranchFactor, "xrpl::selectBranch : maximum result");
126 return branch;
127}
128
129SHAMapNodeID
130SHAMapNodeID::createID(int depth, uint256 const& key)
131{
132 XRPL_ASSERT((depth >= 0) && (depth < 65), "xrpl::SHAMapNodeID::createID : valid branch input");
133 return SHAMapNodeID(depth, key & depthMask(depth));
134}
135
136} // namespace xrpl
static BaseUInt fromVoid(void const *data)
Definition base_uint.h:322
iterator begin()
Definition base_uint.h:117
Identifies a node inside a SHAMap.
static SHAMapNodeID createID(int depth, uint256 const &key)
Create a SHAMapNodeID of a node with the depth of the node and the key of a leaf.
SHAMapNodeID getChildNodeID(unsigned int m) const
SHAMapNodeID()=default
unsigned int depth_
std::string getRawString() const
static constexpr unsigned int kLeafDepth
The depth of the hash map: data is only present in the leaves.
Definition SHAMap.h:100
static constexpr unsigned int kBranchFactor
Number of children each non-leaf node has (the 'radix tree' part of the map).
Definition SHAMap.h:97
int addBitString(BaseUInt< Bits, Tag > const &v)
Definition Serializer.h:105
std::string getString() const
Definition Serializer.h:212
int add8(unsigned char i)
T emplace(T... args)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
std::string to_string(BaseUInt< Bits, Tag > const &a)
Definition base_uint.h:633
static uint256 const & depthMask(unsigned int depth)
unsigned int selectBranch(SHAMapNodeID const &id, uint256 const &hash)
Returns the branch that would contain the given hash.
std::optional< SHAMapNodeID > deserializeSHAMapNodeID(void const *data, std::size_t size)
Return an object representing a serialized SHAMap Node ID.
BaseUInt< 256 > uint256
Definition base_uint.h:562
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
Definition contract.h:49