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, std::move(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)
217 if (
auto nodeData = filter->
getNode(hash))
229 std::move(*nodeData),
239 <<
"Invalid node/data, hash=" << hash <<
": " << x.
what();
288 Throw<SHAMapMissingNode>(
type_, hash);
310 if (!ret && !parent->isEmptyBranch(branch))
311 Throw<SHAMapMissingNode>(
type_, parent->getChildHash(branch));
340 node =
fetchNode(parent->getChildHash(branch));
344 node = parent->canonicalizeChild(branch, std::move(node));
357 ret =
fetchNode(parent->getChildHash(branch));
383 child = childNode.
get();
417 [
this, hash, cb{std::move(callback)}](
419 auto node = finishFetch(hash, object);
433 template <
class Node>
438 assert(node->cowid() <=
cowid_);
439 if (node->cowid() !=
cowid_)
443 node = std::static_pointer_cast<Node>(node->clone(
cowid_));
458 auto& [init, cmp, incr] = loopParams;
461 auto n = std::static_pointer_cast<SHAMapLeafNode>(node);
465 auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
469 stack.
push({inner, stack.
top().second.getChildNodeID(branch)});
470 for (
int i = init; cmp(i);)
472 if (!inner->isEmptyBranch(i))
475 assert(!stack.
empty());
478 auto n = std::static_pointer_cast<SHAMapLeafNode>(node);
482 inner = std::static_pointer_cast<SHAMapInnerNode>(node);
483 stack.
push({inner, stack.
top().second.getChildNodeID(branch)});
498 auto cmp = [](
int i) {
return i >= 0; };
499 auto incr = [](
int& i) { --i; };
501 return belowHelper(node, stack, branch, {init, cmp, incr});
511 auto incr = [](
int& i) { ++i; };
513 return belowHelper(node, stack, branch, {init, cmp, incr});
528 if (!inner->isEmptyBranch(i))
549 assert(leaf->peekItem() || (leaf ==
root_.get()));
550 return leaf->peekItem();
556 assert(stack.
empty());
560 while (!stack.
empty())
570 assert(!stack.
empty());
571 assert(stack.
top().
first->isLeaf());
573 while (!stack.
empty())
575 auto [node, nodeID] = stack.
top();
576 assert(!node->isLeaf());
577 auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
580 if (!inner->isEmptyBranch(i))
585 Throw<SHAMapMissingNode>(
type_,
id);
586 assert(leaf->isLeaf());
624 while (!stack.
empty())
626 auto [node, nodeID] = stack.
top();
630 if (leaf->peekItem()->key() > id)
632 this, leaf->peekItem().get(), std::move(stack));
636 auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
641 if (!inner->isEmptyBranch(branch))
646 Throw<SHAMapMissingNode>(
type_,
id);
648 this, leaf->peekItem().get(), std::move(stack));
661 while (!stack.
empty())
663 auto [node, nodeID] = stack.
top();
667 if (leaf->peekItem()->key() < id)
669 this, leaf->peekItem().get(), std::move(stack));
673 auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
674 for (
int branch =
selectBranch(nodeID,
id) - 1; branch >= 0;
677 if (!inner->isEmptyBranch(branch))
680 auto leaf =
lastBelow(node, stack, branch);
682 Throw<SHAMapMissingNode>(
type_,
id);
684 this, leaf->peekItem().get(), std::move(stack));
697 return (
findKey(
id) !=
nullptr);
710 Throw<SHAMapMissingNode>(
type_,
id);
712 auto leaf = std::dynamic_pointer_cast<SHAMapLeafNode>(stack.
top().
first);
715 if (!leaf || (leaf->peekItem()->key() !=
id))
724 while (!stack.
empty())
727 std::static_pointer_cast<SHAMapInnerNode>(stack.
top().
first);
732 node->setChild(
selectBranch(nodeID,
id), std::move(prevNode));
738 const int bc = node->getBranchCount();
753 if (!node->isEmptyBranch(i))
755 node->setChild(i,
nullptr);
764 prevNode = std::move(node);
770 prevNode = std::move(node);
791 Throw<SHAMapMissingNode>(
type_, tag);
793 auto [node, nodeID] = stack.
top();
798 auto leaf = std::static_pointer_cast<SHAMapLeafNode>(node);
799 if (leaf->peekItem()->key() == tag)
806 auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
808 assert(inner->isEmptyBranch(branch));
815 auto leaf = std::static_pointer_cast<SHAMapLeafNode>(node);
817 assert(otherItem && (tag != otherItem->key()));
819 node = std::make_shared<SHAMapInnerNode>(node->cowid());
826 stack.
push({node, nodeID});
830 nodeID = nodeID.getChildNodeID(b1);
831 node = std::make_shared<SHAMapInnerNode>(
cowid_);
835 assert(node->isInner());
849 return addGiveItem(type, std::make_shared<SHAMapItem const>(std::move(i)));
855 auto hash =
root_->getHash();
859 hash =
root_->getHash();
878 Throw<SHAMapMissingNode>(
type_, tag);
880 auto node = std::dynamic_pointer_cast<SHAMapLeafNode>(stack.
top().
first);
884 if (!node || (node->peekItem()->key() != tag))
890 if (node->getType() != type)
892 JLOG(
journal_.
fatal()) <<
"SHAMap::setItem: cross-type change!";
898 if (node->setItem(std::move(item)))
907 if (hash ==
root_->getHash())
914 stream <<
"Fetch root TXN node " << hash;
918 stream <<
"Fetch root STATE node " << hash;
922 stream <<
"Fetch root SHAMap node " << hash;
931 assert(
root_->getHash() == hash);
953 assert(node->cowid() == 0);
959 node->serializeWithPrefix(s);
968 template <
class Node>
974 assert(node->cowid() != 0);
976 if (node->cowid() !=
cowid_)
980 node = std::static_pointer_cast<Node>(node->clone(
cowid_));
1009 if (
root_->isLeaf())
1012 root_->updateHash();
1021 auto node = std::static_pointer_cast<SHAMapInnerNode>(
root_);
1023 if (node->isEmpty())
1025 root_ = std::make_shared<SHAMapInnerNode>(0);
1043 if (node->isEmptyBranch(pos))
1052 auto child = node->getChild(pos++);
1054 if (child && (child->cowid() != 0))
1060 if (child->isInner())
1064 stack.
emplace(std::move(node), branch);
1068 node = std::static_pointer_cast<SHAMapInnerNode>(
1077 assert(node->cowid() ==
cowid_);
1078 child->updateHash();
1084 node->shareChild(branch, child);
1091 node->updateHashDeep();
1097 node = std::static_pointer_cast<SHAMapInnerNode>(
1105 auto parent = std::move(stack.
top().first);
1106 pos = stack.
top().second;
1110 assert(parent->cowid() ==
cowid_);
1111 parent->shareChild(pos, node);
1114 node = std::move(parent);
1119 root_ = std::move(node);
1135 auto [node, nodeID] = stack.
top();
1144 if (node->isInner())
1149 if (!inner->isEmptyBranch(i))
1151 auto child = inner->getChildPointer(i);
1154 assert(child->getHash() == inner->getChildHash(i));
1155 stack.
push({child, nodeID.getChildNodeID(i)});
1162 }
while (!stack.
empty());
1164 JLOG(
journal_.
info()) << leafCount <<
" resident leaves";
1171 assert(!ret || !ret->cowid());
1181 assert(node->cowid() == 0);
1182 assert(node->getHash() == hash);
1185 ->canonicalize_replace_client(hash.
as_uint256(), node);
1192 auto node =
root_.get();
1193 assert(node !=
nullptr);
1194 assert(!node->isLeaf());
1199 node->invariants(
true);