20 #include <ripple/shamap/SHAMapInnerNode.h>
22 #include <ripple/basics/ByteUtilities.h>
23 #include <ripple/basics/Log.h>
24 #include <ripple/basics/Slice.h>
25 #include <ripple/basics/contract.h>
26 #include <ripple/basics/safe_cast.h>
27 #include <ripple/beast/core/LexicalCast.h>
28 #include <ripple/protocol/HashPrefix.h>
29 #include <ripple/protocol/digest.h>
30 #include <ripple/shamap/SHAMapTreeNode.h>
31 #include <ripple/shamap/impl/TaggedPointer.ipp>
33 #include <openssl/sha.h>
84 auto p = std::make_shared<SHAMapInnerNode>(
cowid, branchCount);
91 std::tie(std::ignore, cloneHashes, cloneChildren) =
92 p->hashesAndChildren_.getHashesAndChildren();
93 std::tie(std::ignore, thisHashes, thisChildren) =
98 int cloneChildIndex = 0;
100 cloneHashes[cloneChildIndex++] = thisHashes[indexNum];
106 cloneHashes[branchNum] = thisHashes[indexNum];
112 int cloneChildIndex = 0;
114 cloneChildren[cloneChildIndex++] = thisChildren[indexNum];
120 cloneChildren[branchNum] = thisChildren[indexNum];
133 if (data.size() != 512)
134 Throw<std::runtime_error>(
"Invalid FI node");
136 auto ret = std::make_shared<SHAMapInnerNode>(0,
branchFactor);
140 auto retHashes = ret->hashesAndChildren_.getHashes();
145 if (retHashes[i].isNonZero())
146 ret->isBranch_ |= (1 << i);
149 ret->resizeChildArrays(ret->getBranchCount());
165 auto ret = std::make_shared<SHAMapInnerNode>(0,
branchFactor);
167 auto retHashes = ret->hashesAndChildren_.getHashes();
168 for (
int i = 0; i < (len / 33); ++i)
172 if (!s.
get8(pos, 32 + (i * 33)))
173 Throw<std::runtime_error>(
"short CI node");
176 Throw<std::runtime_error>(
"invalid CI node");
180 if (retHashes[pos].isNonZero())
181 ret->isBranch_ |= (1 << pos);
184 ret->resizeChildArrays(ret->getBranchCount());
212 std::tie(std::ignore, hashes, children) =
215 if (children[indexNum] !=
nullptr)
216 hashes[indexNum] = children[indexNum]->
getHash();
287 assert(child.get() !=
this);
289 auto const dstIsBranch = [&] {
296 auto const dstToAllocate = popcnt16(dstIsBranch);
308 hashes[childIndex].zero();
309 children[childIndex] = child;
324 assert(child.get() !=
this);
357 return zeroSHAMapHash;
370 assert(node->getHash() == hashes[childIndex]);
373 if (children[childIndex])
376 node = children[childIndex];
381 children[childIndex] = node;
390 auto [numAllocated, hashes, children] =
396 for (
int i = 0; i < branchCount; ++i)
398 assert(hashes[i].isNonZero());
399 if (children[i] !=
nullptr)
400 children[i]->invariants();
408 if (hashes[i].isNonZero())
411 if (children[i] !=
nullptr)
412 children[i]->invariants();
std::uint32_t cowid() const
Returns the SHAMap that owns this node.
void serializeWithPrefix(Serializer &) const override
Serialize the node in a format appropriate for hashing.
void setChild(int m, std::shared_ptr< SHAMapTreeNode > const &child)
std::shared_ptr< SHAMapTreeNode > clone(std::uint32_t cowid) const override
Make a copy of this node, setting the owner.
SHAMapInnerNode(std::uint32_t cowid, std::uint8_t numAllocatedChildren=branchFactor)
std::optional< int > getChildIndex(std::uint16_t isBranch, int i) const
Get the child's index inside the hashes or children array (which may or may not be sparse).
TaggedPointer hashesAndChildren_
Opaque type that contains the hashes array (array of type SHAMapHash) and the children array (array o...
Returns the SHA512-Half digest of a message.
std::shared_ptr< SHAMapTreeNode > getChild(int branch)
An immutable linear range of bytes.
static std::shared_ptr< SHAMapTreeNode > makeFullInner(Slice data, SHAMapHash const &hash, bool hashValid)
virtual std::shared_ptr< SHAMapTreeNode > canonicalizeChild(int branch, std::shared_ptr< SHAMapTreeNode > node)
std::uint32_t cowid_
Determines the owning SHAMap, if any.
int add8(unsigned char i)
void updateHash() override
Recalculate the hash of this node.
static constexpr unsigned int branchFactor
Each inner node has 16 children (the 'radix tree' part of the map)
void shareChild(int m, std::shared_ptr< SHAMapTreeNode > const &child)
static constexpr unsigned const char wireTypeInner
std::string to_string(ListDisposition disposition)
Identifies a node inside a SHAMap.
virtual std::string getString(SHAMapNodeID const &) const
void iterChildren(F &&f) const
Call the f callback for all 16 (branchFactor) branches - even if the branch is empty.
TaggedPointer is a combination of a pointer and a mask stored in the lowest two bits.
bool isEmptyBranch(int m) const
void iterNonEmptyChildIndexes(F &&f) const
Call the f callback for all non-empty branches.
std::string getString(SHAMapNodeID const &) const override
@ innerNode
inner node in V1 tree
SHAMapHash const & getChildHash(int m) const
void resizeChildArrays(std::uint8_t toAllocate)
Convert arrays stored in hashesAndChildren_ so they can store the requested number of children.
SHAMapHash * getHashes() const
Get the hashes array.
bool isDense() const
Check if the arrays have a dense format.
std::optional< int > getChildIndex(int i) const
Get the child's index inside the hashes or children array (stored in hashesAndChildren_.
bool get8(int &, int offset) const
void updateHashDeep()
Recalculate the hash of all children and this node.
int getBranchCount() const
void iterNonEmptyChildIndexes(std::uint16_t isBranch, F &&f) const
Call the f callback for all non-empty branches.
SHAMapHash const & getHash() const
Return the hash of this node.
static constexpr unsigned const char wireTypeCompressedInner
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
void serializeForWire(Serializer &) const override
Serialize the node in a format appropriate for sending over the wire.
int addBitString(base_uint< Bits, Tag > const &v)
bool getBitString(base_uint< Bits, Tag > &data, int offset) const
std::enable_if_t< is_contiguously_hashable< T, Hasher >::value > hash_append(Hasher &h, T const &t) noexcept
Logically concatenate input data to a Hasher.
void hash_append(Hasher &h, Slice const &v)
static std::mutex childLock
std::shared_ptr< SHAMapTreeNode > * getChildren() const
Get the children array.
int add32(std::uint32_t i)
void iterChildren(std::uint16_t isBranch, F &&f) const
Call the f callback for all 16 (branchFactor) branches - even if the branch is empty.
static std::shared_ptr< SHAMapTreeNode > makeCompressedInner(Slice data)
std::tuple< std::uint8_t, SHAMapHash *, std::shared_ptr< SHAMapTreeNode > * > getHashesAndChildren() const
Get the number of elements in each array and a pointer to the start of each array.
uint256 const & as_uint256() const
SHAMapTreeNode * getChildPointer(int branch)
std::uint8_t capacity() const
Get the number of elements allocated for each array.
void invariants(bool is_root=false) const override
std::uint32_t fullBelowGen_