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