20 #include <ripple/basics/random.h> 
   21 #include <ripple/shamap/SHAMap.h> 
   22 #include <ripple/shamap/SHAMapSyncFilter.h> 
   28     std::function<
void(boost::intrusive_ptr<SHAMapItem const> 
const&
 
   29                            item)> 
const& leafFunction)
 const 
   46     if (!
root_->isInner())
 
   52     auto node = std::static_pointer_cast<SHAMapInnerNode>(
root_);
 
   59             if (!node->isEmptyBranch(pos))
 
   63                 if (!
function(*child))
 
   71                     while ((pos != 15) && (node->isEmptyBranch(pos + 1)))
 
   81                     node = std::static_pointer_cast<SHAMapInnerNode>(child);
 
  109     if (
root_->getHash().isZero())
 
  112     if (have && (
root_->getHash() == have->
root_->getHash()))
 
  117         auto leaf = std::static_pointer_cast<SHAMapLeafNode>(
root_);
 
  119             !have->
hasLeafNode(leaf->peekItem()->key(), leaf->getHash()))
 
  129     while (!stack.
empty())
 
  131         auto const [node, nodeID] = stack.
top();
 
  135         if (!
function(*node))
 
  139         for (
int i = 0; i < 16; ++i)
 
  141             if (!node->isEmptyBranch(i))
 
  143                 auto const& childHash = node->getChildHash(i);
 
  159                     if (!
function(*next))
 
  176     int& firstChild = std::get<2>(se);
 
  177     int& currentChild = std::get<3>(se);
 
  178     bool& fullBelow = std::get<4>(se);
 
  180     while (currentChild < 16)
 
  182         int branch = (firstChild + currentChild++) % 16;
 
  196                  ->touch_if_exists(childHash.as_uint256()))
 
  204                 [node, nodeID, branch, &mn](
 
  207                     std::unique_lock<std::mutex> lock{mn.deferLock_};
 
  209                         node, nodeID, branch, std::move(found));
 
  251         node->setFullBelowGen(mn.generation_);
 
  254             f_.getFullBelowCache(ledgerSeq_)
 
  255                 ->insert(node->getHash().as_uint256());
 
  285         auto parent = std::get<0>(deferredNode);
 
  286         auto const& parentID = std::get<1>(deferredNode);
 
  287         auto branch = std::get<2>(deferredNode);
 
  288         auto nodePtr = std::get<3>(deferredNode);
 
  289         auto const& nodeHash = parent->getChildHash(branch);
 
  293             nodePtr = parent->canonicalizeChild(branch, std::move(nodePtr));
 
  302                 parentID.getChildNodeID(branch), nodeHash.as_uint256());
 
  319     assert(root_->getHash().isNonZero());
 
  326         f_.getFullBelowCache(ledgerSeq_)->getGeneration());
 
  328     if (!root_->isInner() ||
 
  329         std::static_pointer_cast<SHAMapInnerNode>(root_)->isFullBelow(
 
  348     auto& node = std::get<0>(pos);
 
  349     auto& nextChild = std::get<3>(pos);
 
  350     auto& fullBelow = std::get<4>(pos);
 
  357             gmn_ProcessNodes(mn, pos);
 
  362             if ((node == 
nullptr) && !mn.
stack_.empty())
 
  365                 bool was = fullBelow;  
 
  377                     fullBelow = fullBelow && was;  
 
  386             gmn_ProcessDeferredReads(mn);
 
  410                 assert(node != 
nullptr);
 
  418     } 
while (node != 
nullptr);
 
  436     auto node = root_.get();
 
  443         if (inner->isEmptyBranch(branch))
 
  445         node = descendThrow(inner, branch);
 
  449     if (node == 
nullptr || wanted != nodeID)
 
  451         JLOG(journal_.info())
 
  452             << 
"peer requested node that is not in the map: " << wanted
 
  453             << 
" but found " << nodeID;
 
  459         JLOG(journal_.warn()) << 
"peer requests empty node";
 
  464     stack.
emplace(node, nodeID, depth);
 
  468     while (!stack.
empty())
 
  475         node->serializeForWire(s);
 
  485             if ((depth > 0) || (bc == 1))
 
  488                 for (
int i = 0; i < 16; ++i)
 
  490                     if (!inner->isEmptyBranch(i))
 
  492                         auto const childNode = descendThrow(inner, i);
 
  495                         if (childNode->isInner() && ((depth > 1) || (bc == 1)))
 
  502                                 (bc > 1) ? (depth - 1) : depth);
 
  504                         else if (childNode->isInner() || fatLeaves)
 
  508                             childNode->serializeForWire(s);
 
  524     root_->serializeForWire(s);
 
  530     Slice const& rootNode,
 
  534     if (root_->getHash().isNonZero())
 
  536         JLOG(journal_.trace()) << 
"got root node, already have one";
 
  537         assert(root_->getHash() == hash);
 
  538         return SHAMapAddNode::duplicate();
 
  542     auto node = SHAMapTreeNode::makeFromWire(rootNode);
 
  543     if (!node || node->getHash() != hash)
 
  544         return SHAMapAddNode::invalid();
 
  547         canonicalize(hash, node);
 
  557         root_->serializeWithPrefix(s);
 
  566     return SHAMapAddNode::useful();
 
  570 SHAMap::addKnownNode(
 
  572     Slice const& rawNode,
 
  579         JLOG(journal_.trace()) << 
"AddKnownNode while not synching";
 
  580         return SHAMapAddNode::duplicate();
 
  583     auto const generation = f_.getFullBelowCache(ledgerSeq_)->getGeneration();
 
  585     auto iNode = root_.get();
 
  587     while (iNode->isInner() &&
 
  594         if (inner->isEmptyBranch(branch))
 
  596             JLOG(journal_.warn()) << 
"Add known node for empty branch" << node;
 
  597             return SHAMapAddNode::invalid();
 
  600         auto childHash = inner->getChildHash(branch);
 
  601         if (f_.getFullBelowCache(ledgerSeq_)
 
  602                 ->touch_if_exists(childHash.as_uint256()))
 
  604             return SHAMapAddNode::duplicate();
 
  607         auto prevNode = inner;
 
  608         std::tie(iNode, iNodeID) = descend(inner, iNodeID, branch, filter);
 
  610         if (iNode == 
nullptr)
 
  612             auto newNode = SHAMapTreeNode::makeFromWire(rawNode);
 
  614             if (!newNode || childHash != newNode->getHash())
 
  616                 JLOG(journal_.warn()) << 
"Corrupt node received";
 
  617                 return SHAMapAddNode::invalid();
 
  623             if ((iNodeID.
getDepth() > leafDepth) ||
 
  624                 (newNode->isInner() && iNodeID.
getDepth() == leafDepth))
 
  627                 state_ = SHAMapState::Invalid;
 
  628                 return SHAMapAddNode::useful();
 
  634                 JLOG(journal_.warn()) << 
"unable to hook node " << node;
 
  635                 JLOG(journal_.info()) << 
" stuck at " << iNodeID;
 
  636                 JLOG(journal_.info()) << 
"got depth=" << node.
getDepth()
 
  637                                       << 
", walked to= " << iNodeID.
getDepth();
 
  638                 return SHAMapAddNode::useful();
 
  642                 canonicalize(childHash, newNode);
 
  644             newNode = prevNode->canonicalizeChild(branch, std::move(newNode));
 
  649                 newNode->serializeWithPrefix(s);
 
  658             return SHAMapAddNode::useful();
 
  662     JLOG(journal_.trace()) << 
"got node, already had it (late)";
 
  663     return SHAMapAddNode::duplicate();
 
  672     stack.
push({root_.get(), other.
root_.get()});
 
  674     while (!stack.
empty())
 
  676         auto const [node, otherNode] = stack.
top();
 
  679         if (!node || !otherNode)
 
  681             JLOG(journal_.info()) << 
"unable to fetch node";
 
  684         else if (otherNode->getHash() != node->getHash())
 
  686             JLOG(journal_.warn()) << 
"node hash mismatch";
 
  692             if (!otherNode->isLeaf())
 
  695             auto& otherNodePeek =
 
  697             if (nodePeek->key() != otherNodePeek->key())
 
  699             if (nodePeek->slice() != otherNodePeek->slice())
 
  702         else if (node->isInner())
 
  704             if (!otherNode->isInner())
 
  708             for (
int i = 0; i < 16; ++i)
 
  710                 if (node_inner->isEmptyBranch(i))
 
  712                     if (!other_inner->isEmptyBranch(i))
 
  717                     if (other_inner->isEmptyBranch(i))
 
  720                     auto next = descend(node_inner, i);
 
  721                     auto otherNext = other.
descend(other_inner, i);
 
  722                     if (!next || !otherNext)
 
  724                         JLOG(journal_.warn()) << 
"unable to fetch inner node";
 
  727                     stack.
push({next, otherNext});
 
  739 SHAMap::hasInnerNode(
 
  743     auto node = root_.get();
 
  750         if (inner->isEmptyBranch(branch))
 
  753         node = descendThrow(inner, branch);
 
  757     return (node->isInner()) && (node->getHash() == targetNodeHash);
 
  765     auto node = root_.get();
 
  768     if (!node->isInner())  
 
  769         return node->getHash() == targetNodeHash;
 
  775         if (inner->isEmptyBranch(branch))
 
  778         if (inner->getChildHash(branch) ==
 
  782         node = descendThrow(inner, branch);
 
  784     } 
while (node->isInner());
 
  791 SHAMap::getProofPath(
uint256 const& key)
 const 
  794     walkTowardsKey(key, &stack);
 
  798         JLOG(journal_.debug()) << 
"no path to " << key;
 
  802     if (
auto const& node = stack.
top().
first; !node || node->isInner() ||
 
  803         std::static_pointer_cast<SHAMapLeafNode>(node)->peekItem()->key() !=
 
  806         JLOG(journal_.debug()) << 
"no path to " << key;
 
  811     path.reserve(stack.
size());
 
  812     while (!stack.
empty())
 
  815         stack.
top().
first->serializeForWire(s);
 
  816         path.emplace_back(std::move(s.
modData()));
 
  820     JLOG(journal_.debug()) << 
"getPath for key " << key << 
", path length " 
  826 SHAMap::verifyProofPath(
 
  831     if (path.empty() || path.size() > 65)
 
  837         for (
auto rit = path.rbegin(); rit != path.rend(); ++rit)
 
  839             auto const& blob = *rit;
 
  840             auto node = SHAMapTreeNode::makeFromWire(
makeSlice(blob));
 
  844             if (node->getHash() != hash)
 
  850                 auto nodeId = SHAMapNodeID::createID(depth, key);
 
  857                 return depth + 1 == path.size();