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