20 #include <ripple/basics/random.h>
21 #include <ripple/shamap/SHAMap.h>
22 #include <ripple/shamap/SHAMapSyncFilter.h>
46 if (!
root_->isInner())
52 auto node = std::static_pointer_cast<SHAMapInnerNode>(
root_);
60 if (!node->isEmptyBranch(pos))
64 if (!
function(*child))
72 while ((pos != 15) && (node->isEmptyBranch(pos + 1)))
82 node = std::static_pointer_cast<SHAMapInnerNode>(child);
110 if (
root_->getHash().isZero())
113 if (have && (
root_->getHash() == have->
root_->getHash()))
118 auto leaf = std::static_pointer_cast<SHAMapLeafNode>(
root_);
120 !have->
hasLeafNode(leaf->peekItem()->key(), leaf->getHash()))
130 while (!stack.
empty())
132 auto const [node, nodeID] = stack.
top();
136 if (!
function(*node))
140 for (
int i = 0; i < 16; ++i)
142 if (!node->isEmptyBranch(i))
144 auto const& childHash = node->getChildHash(i);
160 if (!
function(*next))
177 int& firstChild = std::get<2>(se);
178 int& currentChild = std::get<3>(se);
179 bool& fullBelow = std::get<4>(se);
181 while (currentChild < 16)
183 int branch = (firstChild + currentChild++) % 16;
197 ->touch_if_exists(childHash.as_uint256()))
199 bool pending =
false;
205 [node, nodeID, branch, &mn](
208 std::unique_lock<std::mutex> lock{mn.deferLock_};
210 node, nodeID, branch, std::move(found));
252 node->setFullBelowGen(mn.generation_);
255 f_.getFullBelowCache(ledgerSeq_)
256 ->insert(node->getHash().as_uint256());
286 auto parent = std::get<0>(deferredNode);
287 auto const& parentID = std::get<1>(deferredNode);
288 auto branch = std::get<2>(deferredNode);
289 auto nodePtr = std::get<3>(deferredNode);
290 auto const& nodeHash = parent->getChildHash(branch);
294 nodePtr = parent->canonicalizeChild(branch, std::move(nodePtr));
303 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);
437 auto node = root_.get();
444 if (inner->isEmptyBranch(branch))
447 node = descendThrow(inner, branch);
451 if (node ==
nullptr || wanted != nodeID)
453 JLOG(journal_.warn()) <<
"peer requested node that is not in the map:\n"
454 << wanted <<
" but found\n"
461 JLOG(journal_.warn()) <<
"peer requests empty node";
466 stack.
emplace(node, nodeID, depth);
468 while (!stack.
empty())
476 node->serializeForWire(s);
487 if ((depth > 0) || (bc == 1))
490 for (
int i = 0; i < 16; ++i)
492 if (!inner->isEmptyBranch(i))
494 auto const childNode = descendThrow(inner, i);
497 if (childNode->isInner() && ((depth > 1) || (bc == 1)))
504 (bc > 1) ? (depth - 1) : depth);
506 else if (childNode->isInner() || fatLeaves)
510 childNode->serializeForWire(ns);
526 root_->serializeForWire(s);
532 Slice const& rootNode,
536 if (root_->getHash().isNonZero())
538 JLOG(journal_.trace()) <<
"got root node, already have one";
539 assert(root_->getHash() == hash);
540 return SHAMapAddNode::duplicate();
544 auto node = SHAMapTreeNode::makeFromWire(rootNode);
545 if (!node || node->getHash() != hash)
546 return SHAMapAddNode::invalid();
549 canonicalize(hash, node);
559 root_->serializeWithPrefix(s);
568 return SHAMapAddNode::useful();
572 SHAMap::addKnownNode(
574 Slice const& rawNode,
581 JLOG(journal_.trace()) <<
"AddKnownNode while not synching";
582 return SHAMapAddNode::duplicate();
585 auto const generation = f_.getFullBelowCache(ledgerSeq_)->getGeneration();
586 auto newNode = SHAMapTreeNode::makeFromWire(rawNode);
588 auto iNode = root_.get();
590 while (iNode->isInner() &&
597 if (inner->isEmptyBranch(branch))
599 JLOG(journal_.warn()) <<
"Add known node for empty branch" << node;
600 return SHAMapAddNode::invalid();
603 auto childHash = inner->getChildHash(branch);
604 if (f_.getFullBelowCache(ledgerSeq_)
605 ->touch_if_exists(childHash.as_uint256()))
607 return SHAMapAddNode::duplicate();
610 auto prevNode = inner;
611 std::tie(iNode, iNodeID) = descend(inner, iNodeID, branch, filter);
613 if (iNode ==
nullptr)
615 if (!newNode || childHash != newNode->getHash())
617 JLOG(journal_.warn()) <<
"Corrupt node received";
618 return SHAMapAddNode::invalid();
624 if ((iNodeID.
getDepth() > leafDepth) ||
625 (newNode->isInner() && iNodeID.
getDepth() == leafDepth))
628 state_ = SHAMapState::Invalid;
629 return SHAMapAddNode::useful();
635 JLOG(journal_.warn()) <<
"unable to hook node " << node;
636 JLOG(journal_.info()) <<
" stuck at " << iNodeID;
637 JLOG(journal_.info()) <<
"got depth=" << node.
getDepth()
638 <<
", walked to= " << iNodeID.
getDepth();
639 return SHAMapAddNode::useful();
643 canonicalize(childHash, newNode);
645 newNode = prevNode->canonicalizeChild(branch, std::move(newNode));
650 newNode->serializeWithPrefix(s);
659 return SHAMapAddNode::useful();
663 JLOG(journal_.trace()) <<
"got node, already had it (late)";
664 return SHAMapAddNode::duplicate();
673 stack.
push({root_.get(), other.
root_.get()});
675 while (!stack.
empty())
677 auto const [node, otherNode] = stack.
top();
680 if (!node || !otherNode)
682 JLOG(journal_.info()) <<
"unable to fetch node";
685 else if (otherNode->getHash() != node->getHash())
687 JLOG(journal_.warn()) <<
"node hash mismatch";
693 if (!otherNode->isLeaf())
696 auto& otherNodePeek =
698 if (nodePeek->key() != otherNodePeek->key())
700 if (nodePeek->peekData() != otherNodePeek->peekData())
703 else if (node->isInner())
705 if (!otherNode->isInner())
709 for (
int i = 0; i < 16; ++i)
711 if (node_inner->isEmptyBranch(i))
713 if (!other_inner->isEmptyBranch(i))
718 if (other_inner->isEmptyBranch(i))
721 auto next = descend(node_inner, i);
722 auto otherNext = other.
descend(other_inner, i);
723 if (!next || !otherNext)
725 JLOG(journal_.warn()) <<
"unable to fetch inner node";
728 stack.
push({next, otherNext});
740 SHAMap::hasInnerNode(
744 auto node = root_.get();
751 if (inner->isEmptyBranch(branch))
754 node = descendThrow(inner, branch);
758 return (node->isInner()) && (node->getHash() == targetNodeHash);
766 auto node = root_.get();
769 if (!node->isInner())
770 return node->getHash() == targetNodeHash;
776 if (inner->isEmptyBranch(branch))
779 if (inner->getChildHash(branch) ==
783 node = descendThrow(inner, branch);
785 }
while (node->isInner());