rippled
SHAMapTreeNode.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/basics/Slice.h>
22 #include <ripple/basics/contract.h>
23 #include <ripple/basics/safe_cast.h>
24 #include <ripple/beast/core/LexicalCast.h>
25 #include <ripple/protocol/HashPrefix.h>
26 #include <ripple/protocol/digest.h>
27 #include <ripple/shamap/SHAMapAccountStateLeafNode.h>
28 #include <ripple/shamap/SHAMapInnerNode.h>
29 #include <ripple/shamap/SHAMapLeafNode.h>
30 #include <ripple/shamap/SHAMapTreeNode.h>
31 #include <ripple/shamap/SHAMapTxLeafNode.h>
32 #include <ripple/shamap/SHAMapTxPlusMetaLeafNode.h>
33 #include <mutex>
34 
35 #include <openssl/sha.h>
36 
37 namespace ripple {
38 
41  Slice data,
42  SHAMapHash const& hash,
43  bool hashValid)
44 {
45  // FIXME: using a Serializer results in a copy; avoid it?
46  Serializer s(data.begin(), data.size());
47 
48  auto item = std::make_shared<SHAMapItem const>(
50 
51  if (hashValid)
52  return std::make_shared<SHAMapTxLeafNode>(std::move(item), 0, hash);
53 
54  return std::make_shared<SHAMapTxLeafNode>(std::move(item), 0);
55 }
56 
59  Slice data,
60  SHAMapHash const& hash,
61  bool hashValid)
62 {
63  Serializer s(data.data(), data.size());
64 
65  uint256 tag;
66 
67  if (s.size() < tag.bytes)
68  Throw<std::runtime_error>("Short TXN+MD node");
69 
70  // FIXME: improve this interface so that the above check isn't needed
71  if (!s.getBitString(tag, s.size() - tag.bytes))
72  Throw<std::out_of_range>(
73  "Short TXN+MD node (" + std::to_string(s.size()) + ")");
74 
75  s.chop(tag.bytes);
76 
77  auto item = std::make_shared<SHAMapItem const>(tag, s.peekData());
78 
79  if (hashValid)
80  return std::make_shared<SHAMapTxPlusMetaLeafNode>(
81  std::move(item), 0, hash);
82 
83  return std::make_shared<SHAMapTxPlusMetaLeafNode>(std::move(item), 0);
84 }
85 
88  Slice data,
89  SHAMapHash const& hash,
90  bool hashValid)
91 {
92  Serializer s(data.data(), data.size());
93 
94  uint256 tag;
95 
96  if (s.size() < tag.bytes)
97  Throw<std::runtime_error>("short AS node");
98 
99  // FIXME: improve this interface so that the above check isn't needed
100  if (!s.getBitString(tag, s.size() - tag.bytes))
101  Throw<std::out_of_range>(
102  "Short AS node (" + std::to_string(s.size()) + ")");
103 
104  s.chop(tag.bytes);
105 
106  if (tag.isZero())
107  Throw<std::runtime_error>("Invalid AS node");
108 
109  auto item = std::make_shared<SHAMapItem const>(tag, s.peekData());
110 
111  if (hashValid)
112  return std::make_shared<SHAMapAccountStateLeafNode>(
113  std::move(item), 0, hash);
114 
115  return std::make_shared<SHAMapAccountStateLeafNode>(std::move(item), 0);
116 }
117 
120 {
121  if (rawNode.empty())
122  return {};
123 
124  auto const type = rawNode[rawNode.size() - 1];
125 
126  rawNode.remove_suffix(1);
127 
128  bool const hashValid = false;
129  SHAMapHash const hash;
130 
131  if (type == wireTypeTransaction)
132  return makeTransaction(rawNode, hash, hashValid);
133 
134  if (type == wireTypeAccountState)
135  return makeAccountState(rawNode, hash, hashValid);
136 
137  if (type == wireTypeInner)
138  return SHAMapInnerNode::makeFullInner(rawNode, hash, hashValid);
139 
140  if (type == wireTypeCompressedInner)
141  return SHAMapInnerNode::makeCompressedInner(rawNode);
142 
143  if (type == wireTypeTransactionWithMeta)
144  return makeTransactionWithMeta(rawNode, hash, hashValid);
145 
146  Throw<std::runtime_error>(
147  "wire: Unknown type (" + std::to_string(type) + ")");
148 }
149 
152 {
153  if (rawNode.size() < 4)
154  Throw<std::runtime_error>("prefix: short node");
155 
156  // FIXME: Use SerialIter::get32?
157  // Extract the prefix
158  auto const type = safe_cast<HashPrefix>(
159  (safe_cast<std::uint32_t>(rawNode[0]) << 24) +
160  (safe_cast<std::uint32_t>(rawNode[1]) << 16) +
161  (safe_cast<std::uint32_t>(rawNode[2]) << 8) +
162  (safe_cast<std::uint32_t>(rawNode[3])));
163 
164  rawNode.remove_prefix(4);
165 
166  bool const hashValid = true;
167 
168  if (type == HashPrefix::transactionID)
169  return makeTransaction(rawNode, hash, hashValid);
170 
171  if (type == HashPrefix::leafNode)
172  return makeAccountState(rawNode, hash, hashValid);
173 
174  if (type == HashPrefix::innerNode)
175  return SHAMapInnerNode::makeFullInner(rawNode, hash, hashValid);
176 
177  if (type == HashPrefix::txNode)
178  return makeTransactionWithMeta(rawNode, hash, hashValid);
179 
180  Throw<std::runtime_error>(
181  "prefix: unknown type (" +
183  ")");
184 }
185 
188 {
189  return to_string(id);
190 }
191 
192 } // namespace ripple
ripple::Slice::size
std::size_t size() const noexcept
Returns the number of bytes in the storage.
Definition: Slice.h:79
ripple::Serializer::chop
bool chop(int num)
Definition: Serializer.cpp:176
std::string
STL class.
std::shared_ptr
STL class.
ripple::HashPrefix::txNode
@ txNode
transaction plus metadata
ripple::Slice
An immutable linear range of bytes.
Definition: Slice.h:44
ripple::SHAMapInnerNode::makeFullInner
static std::shared_ptr< SHAMapTreeNode > makeFullInner(Slice data, SHAMapHash const &hash, bool hashValid)
Definition: SHAMapInnerNode.cpp:130
ripple::wireTypeTransaction
static constexpr unsigned const char wireTypeTransaction
Definition: SHAMapTreeNode.h:38
ripple::wireTypeInner
static constexpr unsigned const char wireTypeInner
Definition: SHAMapTreeNode.h:40
ripple::to_string
std::string to_string(ListDisposition disposition)
Definition: ValidatorList.cpp:45
ripple::SHAMapTreeNode::makeFromWire
static std::shared_ptr< SHAMapTreeNode > makeFromWire(Slice rawNode)
Definition: SHAMapTreeNode.cpp:119
ripple::SHAMapNodeID
Identifies a node inside a SHAMap.
Definition: SHAMapNodeID.h:33
ripple::SHAMapTreeNode::getString
virtual std::string getString(SHAMapNodeID const &) const
Definition: SHAMapTreeNode.cpp:187
ripple::Slice::empty
bool empty() const noexcept
Return true if the byte range is empty.
Definition: Slice.h:68
ripple::SHAMapHash
Definition: SHAMapTreeNode.h:47
ripple::wireTypeTransactionWithMeta
static constexpr unsigned const char wireTypeTransactionWithMeta
Definition: SHAMapTreeNode.h:42
std::underlying_type_t
ripple::wireTypeAccountState
static constexpr unsigned const char wireTypeAccountState
Definition: SHAMapTreeNode.h:39
ripple::base_uint< 256 >
ripple::SHAMapTreeNode::makeTransaction
static std::shared_ptr< SHAMapTreeNode > makeTransaction(Slice data, SHAMapHash const &hash, bool hashValid)
Definition: SHAMapTreeNode.cpp:40
ripple::HashPrefix::innerNode
@ innerNode
inner node in V1 tree
ripple::base_uint::bytes
static constexpr std::size_t bytes
Definition: base_uint.h:96
ripple::base_uint::isZero
bool isZero() const
Definition: base_uint.h:439
ripple::SHAMapTreeNode::makeTransactionWithMeta
static std::shared_ptr< SHAMapTreeNode > makeTransactionWithMeta(Slice data, SHAMapHash const &hash, bool hashValid)
Definition: SHAMapTreeNode.cpp:58
ripple::safe_cast
constexpr std::enable_if_t< std::is_same_v< typename Dest::unit_type, typename Src::unit_type > &&std::is_integral_v< typename Dest::value_type > &&std::is_integral_v< typename Src::value_type >, Dest > safe_cast(Src s) noexcept
Definition: FeeUnits.h:537
std::to_string
T to_string(T... args)
ripple::HashPrefix::transactionID
@ transactionID
transaction plus signature to give transaction ID
ripple::HashPrefix::leafNode
@ leafNode
account state
ripple::Serializer
Definition: Serializer.h:39
ripple::wireTypeCompressedInner
static constexpr unsigned const char wireTypeCompressedInner
Definition: SHAMapTreeNode.h:41
ripple::SHAMapTreeNode::makeFromPrefix
static std::shared_ptr< SHAMapTreeNode > makeFromPrefix(Slice rawNode, SHAMapHash const &hash)
Definition: SHAMapTreeNode.cpp:151
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::Serializer::getBitString
bool getBitString(base_uint< Bits, Tag > &data, int offset) const
Definition: Serializer.h:144
ripple::Serializer::size
std::size_t size() const noexcept
Definition: Serializer.h:69
ripple::sha512Half
sha512_half_hasher::result_type sha512Half(Args const &... args)
Returns the SHA512-Half of a series of objects.
Definition: digest.h:216
ripple::Serializer::peekData
Blob const & peekData() const
Definition: Serializer.h:166
ripple::Slice::remove_prefix
void remove_prefix(std::size_t n)
Shrinks the slice by moving its start forward by n characters.
Definition: Slice.h:131
mutex
ripple::SHAMapInnerNode::makeCompressedInner
static std::shared_ptr< SHAMapTreeNode > makeCompressedInner(Slice data)
Definition: SHAMapInnerNode.cpp:161
ripple::Slice::remove_suffix
void remove_suffix(std::size_t n)
Shrinks the slice by moving its end backward by n characters.
Definition: Slice.h:139
ripple::SHAMapTreeNode::makeAccountState
static std::shared_ptr< SHAMapTreeNode > makeAccountState(Slice data, SHAMapHash const &hash, bool hashValid)
Definition: SHAMapTreeNode.cpp:87