1#include <xrpl/basics/IntrusivePointer.ipp> 
    2#include <xrpl/basics/Slice.h> 
    3#include <xrpl/basics/contract.h> 
    4#include <xrpl/basics/spinlock.h> 
    5#include <xrpl/protocol/HashPrefix.h> 
    6#include <xrpl/protocol/digest.h> 
    7#include <xrpl/shamap/SHAMapInnerNode.h> 
    8#include <xrpl/shamap/SHAMapTreeNode.h> 
    9#include <xrpl/shamap/detail/TaggedPointer.ipp> 
   27    std::tie(std::ignore, std::ignore, children) =
 
   30        [&](
auto branchNum, 
auto indexNum) { children[indexNum].
reset(); });
 
 
   65    auto p = intr_ptr::make_shared<SHAMapInnerNode>(
cowid, branchCount);
 
   72    std::tie(std::ignore, cloneHashes, cloneChildren) =
 
   73        p->hashesAndChildren_.getHashesAndChildren();
 
   74    std::tie(std::ignore, thisHashes, thisChildren) =
 
   79        int cloneChildIndex = 0;
 
   81            cloneHashes[cloneChildIndex++] = thisHashes[indexNum];
 
   87            cloneHashes[branchNum] = thisHashes[indexNum];
 
   96        int cloneChildIndex = 0;
 
   98            cloneChildren[cloneChildIndex++] = thisChildren[indexNum];
 
  104            cloneChildren[branchNum] = thisChildren[indexNum];
 
 
  119        Throw<std::runtime_error>(
"Invalid FI node");
 
  121    auto ret = intr_ptr::make_shared<SHAMapInnerNode>(0, 
branchFactor);
 
  125    auto hashes = ret->hashesAndChildren_.getHashes();
 
  131        if (hashes[i].isNonZero())
 
  132            ret->isBranch_ |= (1 << i);
 
  135    ret->resizeChildArrays(ret->getBranchCount());
 
 
  152    if (
auto const s = data.size();
 
  154        Throw<std::runtime_error>(
"Invalid CI node");
 
  158    auto ret = intr_ptr::make_shared<SHAMapInnerNode>(0, 
branchFactor);
 
  160    auto hashes = ret->hashesAndChildren_.getHashes();
 
  165        auto const pos = si.
get8();
 
  168            Throw<std::runtime_error>(
"invalid CI node");
 
  170        hashes[pos].as_uint256() = hash;
 
  172        if (hashes[pos].isNonZero())
 
  173            ret->isBranch_ |= (1 << pos);
 
  176    ret->resizeChildArrays(ret->getBranchCount());
 
 
  202    std::tie(std::ignore, hashes, children) =
 
  205        if (
auto p = children[indexNum].
get())
 
  206            hashes[indexNum] = p->getHash();
 
 
  215        !
isEmpty(), 
"ripple::SHAMapInnerNode::serializeForWire : is non-empty");
 
 
  241        "ripple::SHAMapInnerNode::serializeWithPrefix : is non-empty");
 
 
  268        "ripple::SHAMapInnerNode::setChild : valid branch input");
 
  269    XRPL_ASSERT(
cowid_, 
"ripple::SHAMapInnerNode::setChild : nonzero cowid");
 
  272        "ripple::SHAMapInnerNode::setChild : valid child input");
 
  274    auto const dstIsBranch = [&] {
 
  281    auto const dstToAllocate = 
popcnt16(dstIsBranch);
 
  293        hashes[childIndex].zero();
 
  294        children[childIndex] = std::move(child);
 
  301        "ripple::SHAMapInnerNode::setChild : maximum branch count");
 
 
  312        "ripple::SHAMapInnerNode::shareChild : valid branch input");
 
  313    XRPL_ASSERT(
cowid_, 
"ripple::SHAMapInnerNode::shareChild : nonzero cowid");
 
  315        child, 
"ripple::SHAMapInnerNode::shareChild : non-null child input");
 
  318        "ripple::SHAMapInnerNode::shareChild : valid child input");
 
  322        "ripple::SHAMapInnerNode::shareChild : non-empty branch input");
 
 
  331        "ripple::SHAMapInnerNode::getChildPointer : valid branch input");
 
  334        "ripple::SHAMapInnerNode::getChildPointer : non-empty branch input");
 
 
  348        "ripple::SHAMapInnerNode::getChild : valid branch input");
 
  351        "ripple::SHAMapInnerNode::getChild : non-empty branch input");
 
 
  365        "ripple::SHAMapInnerNode::getChildHash : valid branch input");
 
  369    return zeroSHAMapHash;
 
 
  379        "ripple::SHAMapInnerNode::canonicalizeChild : valid branch input");
 
  382        "ripple::SHAMapInnerNode::canonicalizeChild : valid node input");
 
  385        "ripple::SHAMapInnerNode::canonicalizeChild : non-empty branch input");
 
  389        node->getHash() == hashes[childIndex],
 
  390        "ripple::SHAMapInnerNode::canonicalizeChild : node and branch inputs " 
  396    if (children[childIndex])
 
  399        node = children[childIndex];
 
  404        children[childIndex] = node;
 
 
  412    [[maybe_unused]] 
unsigned count = 0;
 
  413    auto [numAllocated, hashes, children] =
 
  419        for (
int i = 0; i < branchCount; ++i)
 
  422                hashes[i].isNonZero(),
 
  423                "ripple::SHAMapInnerNode::invariants : nonzero hash in branch");
 
  424            if (children[i] != 
nullptr)
 
  425                children[i]->invariants();
 
  433            if (hashes[i].isNonZero())
 
  437                    "ripple::SHAMapInnerNode::invariants : valid branch when " 
  439                if (children[i] != 
nullptr)
 
  440                    children[i]->invariants();
 
  447                    "ripple::SHAMapInnerNode::invariants : valid branch when " 
  457            "ripple::SHAMapInnerNode::invariants : nonzero hash");
 
  459            count >= 1, 
"ripple::SHAMapInnerNode::invariants : minimum count");
 
  463        "ripple::SHAMapInnerNode::invariants : hash and count do match");
 
 
uint256 const & as_uint256() const
 
std::uint32_t fullBelowGen_
 
std::optional< int > getChildIndex(int i) const
Get the child's index inside the hashes or children array (stored in hashesAndChildren_.
 
SHAMapInnerNode(std::uint32_t cowid, std::uint8_t numAllocatedChildren=2)
 
void setChild(int m, intr_ptr::SharedPtr< SHAMapTreeNode > child)
 
static intr_ptr::SharedPtr< SHAMapTreeNode > makeCompressedInner(Slice data)
 
intr_ptr::SharedPtr< SHAMapTreeNode > clone(std::uint32_t cowid) const override
Make a copy of this node, setting the owner.
 
static constexpr unsigned int branchFactor
Each inner node has 16 children (the 'radix tree' part of the map)
 
bool isEmptyBranch(int m) const
 
void iterNonEmptyChildIndexes(F &&f) const
Call the f callback for all non-empty branches.
 
void serializeWithPrefix(Serializer &) const override
Serialize the node in a format appropriate for hashing.
 
void iterChildren(F &&f) const
Call the f callback for all 16 (branchFactor) branches - even if the branch is empty.
 
void resizeChildArrays(std::uint8_t toAllocate)
Convert arrays stored in hashesAndChildren_ so they can store the requested number of children.
 
void updateHash() override
Recalculate the hash of this node.
 
intr_ptr::SharedPtr< SHAMapTreeNode > getChild(int branch)
 
void partialDestructor() override
 
void shareChild(int m, intr_ptr::SharedPtr< SHAMapTreeNode > const &child)
 
SHAMapHash const & getChildHash(int m) const
 
void invariants(bool is_root=false) const override
 
std::string getString(SHAMapNodeID const &) const override
 
intr_ptr::SharedPtr< SHAMapTreeNode > canonicalizeChild(int branch, intr_ptr::SharedPtr< SHAMapTreeNode > node)
 
TaggedPointer hashesAndChildren_
Opaque type that contains the hashes array (array of type SHAMapHash) and the children array (array o...
 
void serializeForWire(Serializer &) const override
Serialize the node in a format appropriate for sending over the wire.
 
void updateHashDeep()
Recalculate the hash of all children and this node.
 
int getBranchCount() const
 
SHAMapTreeNode * getChildPointer(int branch)
 
std::atomic< std::uint16_t > lock_
A bitlock for the children of this node, with one bit per child.
 
static intr_ptr::SharedPtr< SHAMapTreeNode > makeFullInner(Slice data, SHAMapHash const &hash, bool hashValid)
 
Identifies a node inside a SHAMap.
 
virtual std::string getString(SHAMapNodeID const &) const
 
std::uint32_t cowid_
Determines the owning SHAMap, if any.
 
base_uint< Bits, Tag > getBitString()
 
std::size_t empty() const noexcept
 
int addBitString(base_uint< Bits, Tag > const &v)
 
int add8(unsigned char i)
 
A shared intrusive pointer class that supports weak pointers.
 
void reset()
Set the pointer to null, decrement the strong count, and run the appropriate release action.
 
An immutable linear range of bytes.
 
TaggedPointer is a combination of a pointer and a mask stored in the lowest two bits.
 
void iterNonEmptyChildIndexes(std::uint16_t isBranch, F &&f) const
Call the f callback for all non-empty branches.
 
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).
 
std::tuple< std::uint8_t, SHAMapHash *, intr_ptr::SharedPtr< SHAMapTreeNode > * > getHashesAndChildren() const
Get the number of elements in each array and a pointer to the start of each array.
 
SHAMapHash * getHashes() const
Get the hashes array.
 
std::uint8_t capacity() const
Get the number of elements allocated for each array.
 
void iterChildren(std::uint16_t isBranch, F &&f) const
Call the f callback for all 16 (branchFactor) branches - even if the branch is empty.
 
bool isDense() const
Check if the arrays have a dense format.
 
intr_ptr::SharedPtr< SHAMapTreeNode > * getChildren() const
Get the children array.
 
static std::size_t constexpr bytes
 
Classes to handle arrays of spinlocks packed into a single atomic integer:
 
A spinlock implemented on top of an atomic integer.
 
std::uint32_t cowid() const
Returns the SHAMap that owns this node.
 
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.
 
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
 
void hash_append(Hasher &h, Slice const &v)
 
static constexpr unsigned char const wireTypeCompressedInner
 
std::string to_string(base_uint< Bits, Tag > const &a)
 
T get(Section const §ion, std::string const &name, T const &defaultValue=T{})
Retrieve a key/value pair from a section.
 
static constexpr unsigned char const wireTypeInner
 
@ innerNode
inner node in V1 tree
 
int popcnt16(std::uint16_t a)
 
Returns the SHA512-Half digest of a message.