20 #include <ripple/basics/contract.h>
21 #include <ripple/shamap/SHAMap.h>
22 #include <ripple/shamap/SHAMapAccountStateLeafNode.h>
23 #include <ripple/shamap/SHAMapNodeID.h>
24 #include <ripple/shamap/SHAMapSyncFilter.h>
25 #include <ripple/shamap/SHAMapTxLeafNode.h>
26 #include <ripple/shamap/SHAMapTxPlusMetaLeafNode.h>
37 return std::make_shared<SHAMapTxLeafNode>(std::move(item), owner);
40 return std::make_shared<SHAMapTxPlusMetaLeafNode>(
41 std::move(item), owner);
44 return std::make_shared<SHAMapAccountStateLeafNode>(
45 std::move(item), owner);
48 "Attempt to create leaf node of unknown type " +
72 auto ret = std::make_shared<SHAMap>(
type_,
f_);
107 assert(child && (child->cowid() ==
cowid_));
109 while (!stack.
empty())
112 std::dynamic_pointer_cast<SHAMapInnerNode>(stack.
top().
first);
115 assert(node !=
nullptr);
121 node->setChild(branch, child);
123 child = std::move(node);
130 assert(stack ==
nullptr || stack->
empty());
134 while (inNode->isInner())
136 if (stack !=
nullptr)
137 stack->
push({inNode, nodeID});
139 auto const inner = std::static_pointer_cast<SHAMapInnerNode>(inNode);
141 if (inner->isEmptyBranch(branch))
148 if (stack !=
nullptr)
149 stack->
push({inNode, nodeID});
157 if (leaf && leaf->
peekItem()->key() !=
id)
169 if (
auto nodeObject =
199 if (
auto nodeData = filter->
getNode(hash))
211 std::move(*nodeData),
221 <<
"Invalid node/data, hash=" << hash <<
": " << x.
what();
270 Throw<SHAMapMissingNode>(
type_, hash);
292 if (!ret && !parent->isEmptyBranch(branch))
293 Throw<SHAMapMissingNode>(
type_, parent->getChildHash(branch));
322 node =
fetchNode(parent->getChildHash(branch));
326 node = parent->canonicalizeChild(branch, std::move(node));
339 ret =
fetchNode(parent->getChildHash(branch));
365 child = childNode.
get();
417 template <
class Node>
422 assert(node->cowid() <=
cowid_);
423 if (node->cowid() !=
cowid_)
427 node = std::static_pointer_cast<Node>(node->clone(
cowid_));
443 auto n = std::static_pointer_cast<SHAMapLeafNode>(node);
447 auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
451 stack.
push({inner, stack.
top().second.getChildNodeID(branch)});
454 if (!inner->isEmptyBranch(i))
457 assert(!stack.
empty());
460 auto n = std::static_pointer_cast<SHAMapLeafNode>(node);
464 inner = std::static_pointer_cast<SHAMapInnerNode>(node);
465 stack.
push({inner, stack.
top().second.getChildNodeID(branch)});
487 if (!inner->isEmptyBranch(i))
508 assert(leaf->peekItem() || (leaf ==
root_.get()));
509 return leaf->peekItem();
515 assert(stack.
empty());
519 while (!stack.
empty())
529 assert(!stack.
empty());
530 assert(stack.
top().
first->isLeaf());
532 while (!stack.
empty())
534 auto [node, nodeID] = stack.
top();
535 assert(!node->isLeaf());
536 auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
539 if (!inner->isEmptyBranch(i))
544 Throw<SHAMapMissingNode>(
type_,
id);
545 assert(leaf->isLeaf());
585 while (!stack.
empty())
587 auto [node, nodeID] = stack.
top();
591 if (leaf->peekItem()->key() > id)
593 this, leaf->peekItem().get(), std::move(stack));
597 auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
602 if (!inner->isEmptyBranch(branch))
607 Throw<SHAMapMissingNode>(
type_,
id);
609 this, leaf->peekItem().get(), std::move(stack));
621 return (
findKey(
id) !=
nullptr);
634 Throw<SHAMapMissingNode>(
type_,
id);
636 auto leaf = std::dynamic_pointer_cast<SHAMapLeafNode>(stack.
top().
first);
639 if (!leaf || (leaf->peekItem()->key() !=
id))
648 while (!stack.
empty())
651 std::static_pointer_cast<SHAMapInnerNode>(stack.
top().
first);
662 const int bc = node->getBranchCount();
677 if (!node->isEmptyBranch(i))
679 node->setChild(i,
nullptr);
688 prevNode = std::move(node);
694 prevNode = std::move(node);
715 Throw<SHAMapMissingNode>(
type_, tag);
717 auto [node, nodeID] = stack.
top();
722 auto leaf = std::static_pointer_cast<SHAMapLeafNode>(node);
723 if (leaf->peekItem()->key() == tag)
730 auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
732 assert(inner->isEmptyBranch(branch));
734 inner->setChild(branch, newNode);
740 auto leaf = std::static_pointer_cast<SHAMapLeafNode>(node);
742 assert(otherItem && (tag != otherItem->key()));
744 node = std::make_shared<SHAMapInnerNode>(node->cowid());
751 stack.
push({node, nodeID});
755 nodeID = nodeID.getChildNodeID(b1);
756 node = std::make_shared<SHAMapInnerNode>(
cowid_);
760 assert(node->isInner());
774 return addGiveItem(type, std::make_shared<SHAMapItem const>(std::move(i)));
780 auto hash =
root_->getHash();
784 hash =
root_->getHash();
803 Throw<SHAMapMissingNode>(
type_, tag);
805 auto node = std::dynamic_pointer_cast<SHAMapLeafNode>(stack.
top().
first);
809 if (!node || (node->peekItem()->key() != tag))
815 if (node->getType() != type)
817 JLOG(
journal_.
fatal()) <<
"SHAMap::setItem: cross-type change!";
823 if (node->setItem(std::move(item)))
832 if (hash ==
root_->getHash())
839 stream <<
"Fetch root TXN node " << hash;
843 stream <<
"Fetch root STATE node " << hash;
847 stream <<
"Fetch root SHAMap node " << hash;
856 assert(
root_->getHash() == hash);
878 assert(node->cowid() == 0);
884 node->serializeWithPrefix(s);
893 template <
class Node>
899 assert(node->cowid() != 0);
901 if (node->cowid() !=
cowid_)
905 node = std::static_pointer_cast<Node>(node->clone(
cowid_));
946 auto node = std::static_pointer_cast<SHAMapInnerNode>(
root_);
950 root_ = std::make_shared<SHAMapInnerNode>(0);
968 if (node->isEmptyBranch(pos))
977 auto child = node->getChild(pos++);
979 if (child && (child->cowid() != 0))
985 if (child->isInner())
989 stack.
emplace(std::move(node), branch);
993 node = std::static_pointer_cast<SHAMapInnerNode>(
1002 assert(node->cowid() ==
cowid_);
1003 child->updateHash();
1009 node->shareChild(branch, child);
1016 node->updateHashDeep();
1022 node = std::static_pointer_cast<SHAMapInnerNode>(
1030 auto parent = std::move(stack.
top().first);
1031 pos = stack.
top().second;
1035 assert(parent->cowid() ==
cowid_);
1036 parent->shareChild(pos, node);
1039 node = std::move(parent);
1044 root_ = std::move(node);
1060 auto [node, nodeID] = stack.
top();
1069 if (node->isInner())
1074 if (!inner->isEmptyBranch(i))
1076 auto child = inner->getChildPointer(i);
1079 assert(child->getHash() == inner->getChildHash(i));
1080 stack.
push({child, nodeID.getChildNodeID(i)});
1087 }
while (!stack.
empty());
1089 JLOG(
journal_.
info()) << leafCount <<
" resident leaves";
1096 assert(!ret || !ret->cowid());
1106 assert(node->cowid() == 0);
1107 assert(node->getHash() == hash);
1110 ->canonicalize_replace_client(hash.
as_uint256(), node);
1117 auto node =
root_.get();
1118 assert(node !=
nullptr);
1119 assert(!node->isLeaf());
1124 node->invariants(
true);