rippled
SHAMapNodeID.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/basics/Log.h>
21 #include <ripple/beast/core/LexicalCast.h>
22 #include <ripple/crypto/csprng.h>
23 #include <ripple/shamap/SHAMapNodeID.h>
24 #include <boost/format.hpp>
25 #include <cassert>
26 #include <cstring>
27 
28 namespace ripple {
29 
30 uint256 const&
32 {
33  enum { mask_size = 65 };
34 
35  struct masks_t
36  {
37  uint256 entry[mask_size];
38 
39  masks_t()
40  {
41  uint256 selector;
42  for (int i = 0; i < mask_size - 1; i += 2)
43  {
44  entry[i] = selector;
45  *(selector.begin() + (i / 2)) = 0xF0;
46  entry[i + 1] = selector;
47  *(selector.begin() + (i / 2)) = 0xFF;
48  }
49  entry[mask_size - 1] = selector;
50  }
51  };
52  static masks_t const masks;
53  return masks.entry[depth];
54 }
55 
56 // canonicalize the hash to a node ID for this depth
57 SHAMapNodeID::SHAMapNodeID(int depth, uint256 const& hash)
58  : mNodeID(hash), mDepth(depth)
59 {
60  assert((depth >= 0) && (depth < 65));
61  assert(mNodeID == (mNodeID & Masks(depth)));
62 }
63 
64 SHAMapNodeID::SHAMapNodeID(void const* ptr, int len)
65 {
66  if (len < 33)
67  mDepth = -1;
68  else
69  {
70  std::memcpy(mNodeID.begin(), ptr, 32);
71  mDepth = *(static_cast<unsigned char const*>(ptr) + 32);
72  }
73 }
74 
77 {
78  if ((mDepth == 0) && (mNodeID.isZero()))
79  return "NodeID(root)";
80 
81  return "NodeID(" + std::to_string(mDepth) + "," + to_string(mNodeID) + ")";
82 }
83 
84 void
86 {
88  s.add8(mDepth);
89 }
90 
93 {
94  Serializer s(33);
95  addIDRaw(s);
96  return s.getString();
97 }
98 
99 // This can be optimized to avoid the << if needed
102 {
103  assert((m >= 0) && (m < 16));
104  assert(mDepth < 64);
105 
106  uint256 child(mNodeID);
107  child.begin()[mDepth / 2] |= (mDepth & 1) ? m : (m << 4);
108 
109  return SHAMapNodeID(mDepth + 1, child);
110 }
111 
112 // Which branch would contain the specified hash
113 int
115 {
116  int branch = *(hash.begin() + (mDepth / 2));
117 
118  if (mDepth & 1)
119  branch &= 0xf;
120  else
121  branch >>= 4;
122 
123  assert((branch >= 0) && (branch < 16));
124 
125  return branch;
126 }
127 
128 bool
130 {
131  assert(mDepth <= other.mDepth);
132  auto x = mNodeID.begin();
133  auto y = other.mNodeID.begin();
134  for (unsigned i = 0; i < mDepth / 2; ++i, ++x, ++y)
135  {
136  if (*x != *y)
137  return false;
138  }
139  if (mDepth & 1)
140  {
141  auto i = mDepth / 2;
142  return (*(mNodeID.begin() + i) & 0xF0) ==
143  (*(other.mNodeID.begin() + i) & 0xF0);
144  }
145  return true;
146 }
147 
148 void
150 {
151  JLOG(journal.debug()) << getString();
152 }
153 
154 } // namespace ripple
ripple::SHAMapNodeID::selectBranch
int selectBranch(uint256 const &hash) const
Definition: SHAMapNodeID.cpp:114
std::string
STL class.
cstring
ripple::SHAMapNodeID::getChildNodeID
SHAMapNodeID getChildNodeID(int m) const
Definition: SHAMapNodeID.cpp:101
ripple::Serializer::getString
std::string getString() const
Definition: Serializer.h:202
ripple::Serializer::add8
int add8(unsigned char i)
Definition: Serializer.cpp:158
ripple::to_string
std::string to_string(ListDisposition disposition)
Definition: ValidatorList.cpp:42
ripple::SHAMapNodeID
Definition: SHAMapNodeID.h:33
ripple::uint256
base_uint< 256 > uint256
Definition: base_uint.h:493
ripple::base_uint< 256 >
ripple::SHAMapNodeID::mDepth
int mDepth
Definition: SHAMapNodeID.h:37
ripple::base_uint::isZero
bool isZero() const
Definition: base_uint.h:475
ripple::SHAMapNodeID::getRawString
std::string getRawString() const
Definition: SHAMapNodeID.cpp:92
std::to_string
T to_string(T... args)
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
ripple::Serializer
Definition: Serializer.h:39
ripple::SHAMapNodeID::addIDRaw
void addIDRaw(Serializer &s) const
Definition: SHAMapNodeID.cpp:85
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::Serializer::addBitString
int addBitString(base_uint< Bits, Tag > const &v)
Definition: Serializer.h:97
ripple::base_uint::begin
iterator begin()
Definition: base_uint.h:114
ripple::SHAMapNodeID::SHAMapNodeID
SHAMapNodeID()
Definition: SHAMapNodeID.h:101
cassert
ripple::SHAMapNodeID::getString
std::string getString() const
Definition: SHAMapNodeID.cpp:76
ripple::SHAMapNodeID::Masks
static uint256 const & Masks(int depth)
Definition: SHAMapNodeID.cpp:31
ripple::SHAMapNodeID::mNodeID
uint256 mNodeID
Definition: SHAMapNodeID.h:36
beast::Journal::debug
Stream debug() const
Definition: Journal.h:315
std::memcpy
T memcpy(T... args)
ripple::SHAMapNodeID::dump
void dump(beast::Journal journal) const
Definition: SHAMapNodeID.cpp:149
ripple::SHAMapNodeID::has_common_prefix
bool has_common_prefix(SHAMapNodeID const &other) const
Definition: SHAMapNodeID.cpp:129