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 xrpl {
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) : id_(hash), depth_(depth)
38{
39 XRPL_ASSERT(
40 depth <= SHAMap::leafDepth, "xrpl::SHAMapNodeID::SHAMapNodeID : maximum depth input");
41 XRPL_ASSERT(
42 id_ == (id_ & depthMask(depth)),
43 "xrpl::SHAMapNodeID::SHAMapNodeID : hash and depth inputs do match");
44}
45
48{
49 Serializer s(33);
51 s.add8(depth_);
52 return s.getString();
53}
54
56SHAMapNodeID::getChildNodeID(unsigned int m) const
57{
58 XRPL_ASSERT(
59 m < SHAMap::branchFactor, "xrpl::SHAMapNodeID::getChildNodeID : valid branch input");
60
61 // A SHAMap has exactly 65 levels, so nodes must not exceed that
62 // depth; if they do, this breaks the invariant of never allowing
63 // the construction of a SHAMapNodeID at an invalid depth. We assert
64 // to catch this in debug builds.
65 //
66 // We throw (but never assert) if the node is at level 64, since
67 // entries at that depth are leaf nodes and have no children and even
68 // constructing a child node from them would break the above invariant.
69 XRPL_ASSERT(
70 depth_ <= SHAMap::leafDepth, "xrpl::SHAMapNodeID::getChildNodeID : maximum leaf depth");
71
73 Throw<std::logic_error>("Request for child node ID of " + to_string(*this));
74
75 if (id_ != (id_ & depthMask(depth_)))
76 Throw<std::logic_error>("Incorrect mask for " + to_string(*this));
77
78 SHAMapNodeID node{depth_ + 1, id_};
79 node.id_.begin()[depth_ / 2] |= (depth_ & 1) ? m : (m << 4);
80 return node;
81}
82
84deserializeSHAMapNodeID(void const* data, std::size_t size)
85{
87
88 if (size == 33)
89 {
90 unsigned int depth = *(static_cast<unsigned char const*>(data) + 32);
91 if (depth <= SHAMap::leafDepth)
92 {
93 auto const id = uint256::fromVoid(data);
94
95 if (id == (id & depthMask(depth)))
96 ret.emplace(depth, id);
97 }
98 }
99
100 return ret;
101}
102
103[[nodiscard]] unsigned int
104selectBranch(SHAMapNodeID const& id, uint256 const& hash)
105{
106 auto const depth = id.getDepth();
107 auto branch = static_cast<unsigned int>(*(hash.begin() + (depth / 2)));
108
109 if (depth & 1)
110 branch &= 0xf;
111 else
112 branch >>= 4;
113
114 XRPL_ASSERT(branch < SHAMap::branchFactor, "xrpl::selectBranch : maximum result");
115 return branch;
116}
117
118SHAMapNodeID
119SHAMapNodeID::createID(int depth, uint256 const& key)
120{
121 XRPL_ASSERT((depth >= 0) && (depth < 65), "xrpl::SHAMapNodeID::createID : valid branch input");
122 return SHAMapNodeID(depth, key & depthMask(depth));
123}
124
125} // namespace xrpl
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 leafDepth
The depth of the hash map: data is only present in the leaves.
Definition SHAMap.h:100
static constexpr unsigned int branchFactor
Number of children each non-leaf node has (the 'radix tree' part of the map)
Definition SHAMap.h:97
int addBitString(base_uint< Bits, Tag > const &v)
Definition Serializer.h:105
std::string getString() const
Definition Serializer.h:212
int add8(unsigned char i)
static base_uint fromVoid(void const *data)
Definition base_uint.h:293
iterator begin()
Definition base_uint.h:112
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(base_uint< Bits, Tag > const &a)
Definition base_uint.h:600
static uint256 const & depthMask(unsigned int depth)
base_uint< 256 > uint256
Definition base_uint.h:529
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.