20 #include <ripple/basics/contract.h>
21 #include <ripple/shamap/SHAMap.h>
27 , journal_(f.journal())
32 root_ = std::make_shared<SHAMapInnerNode>(
seq_);
37 , journal_(f.journal())
42 root_ = std::make_shared<SHAMapInnerNode>(
seq_);
53 auto ret = std::make_shared<SHAMap>(
type_,
f_);
88 assert(child && (child->getSeq() ==
seq_));
90 while (!stack.
empty())
93 std::dynamic_pointer_cast<SHAMapInnerNode>(stack.
top().
first);
96 assert(node !=
nullptr);
102 node->setChild(branch, child);
104 child = std::move(node);
111 assert(stack ==
nullptr || stack->
empty());
115 while (inNode->isInner())
117 if (stack !=
nullptr)
118 stack->
push({inNode, nodeID});
120 auto const inner = std::static_pointer_cast<SHAMapInnerNode>(inNode);
122 if (inner->isEmptyBranch(branch))
129 if (stack !=
nullptr)
130 stack->
push({inNode, nodeID});
138 if (leaf && leaf->
peekItem()->key() !=
id)
173 const_cast<bool&
>(
full_) =
false;
185 if (
auto nodeData = filter->
getNode(hash))
192 true, hash,
ledgerSeq_, std::move(*nodeData), node->getType());
243 Throw<SHAMapMissingNode>(
type_, hash);
265 if (!ret && !parent->isEmptyBranch(branch))
266 Throw<SHAMapMissingNode>(
type_, parent->getChildHash(branch));
295 node =
fetchNode(parent->getChildHash(branch));
299 node = parent->canonicalizeChild(branch, std::move(node));
312 ret =
fetchNode(parent->getChildHash(branch));
324 assert((branch >= 0) && (branch < 16));
338 child = childNode.
get();
395 template <
class Node>
400 assert(node->isValid());
401 assert(node->getSeq() <=
seq_);
402 if (node->getSeq() !=
seq_)
406 node = std::static_pointer_cast<Node>(node->clone(
seq_));
407 assert(node->isValid());
423 auto n = std::static_pointer_cast<SHAMapTreeNode>(node);
424 stack.
push({node, {64, n->peekItem()->key()}});
427 auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
431 stack.
push({inner, stack.
top().second.getChildNodeID(branch)});
432 for (
int i = 0; i < 16;)
434 if (!inner->isEmptyBranch(i))
437 assert(!stack.
empty());
440 auto n = std::static_pointer_cast<SHAMapTreeNode>(node);
441 stack.
push({n, {64, n->peekItem()->key()}});
444 inner = std::static_pointer_cast<SHAMapInnerNode>(node);
445 stack.
push({inner, stack.
top().second.getChildNodeID(branch)});
465 for (
int i = 0; i < 16; ++i)
467 if (!inner->isEmptyBranch(i))
488 assert(leaf->hasItem() || (leaf ==
root_.get()));
490 return leaf->peekItem();
498 assert(stack.
empty());
502 while (!stack.
empty())
512 assert(!stack.
empty());
513 assert(stack.
top().
first->isLeaf());
515 while (!stack.
empty())
517 auto [node, nodeID] = stack.
top();
518 assert(!node->isLeaf());
519 auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
520 for (
auto i = nodeID.selectBranch(
id) + 1; i < 16; ++i)
522 if (!inner->isEmptyBranch(i))
527 Throw<SHAMapMissingNode>(
type_,
id);
528 assert(leaf->isLeaf());
580 while (!stack.
empty())
582 auto [node, nodeID] = stack.
top();
586 if (leaf->peekItem()->key() > id)
588 this, leaf->peekItem().get(), std::move(stack));
592 auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
593 for (
auto branch = nodeID.selectBranch(
id) + 1; branch < 16;
596 if (!inner->isEmptyBranch(branch))
601 Throw<SHAMapMissingNode>(
type_,
id);
603 this, leaf->peekItem().get(), std::move(stack));
617 return (leaf !=
nullptr);
630 Throw<SHAMapMissingNode>(
type_,
id);
632 auto leaf = std::dynamic_pointer_cast<SHAMapTreeNode>(stack.
top().
first);
635 if (!leaf || (leaf->peekItem()->key() !=
id))
644 while (!stack.
empty())
647 std::static_pointer_cast<SHAMapInnerNode>(stack.
top().
first);
658 const int bc = node->getBranchCount();
671 for (
int i = 0; i < 16; ++i)
673 if (!node->isEmptyBranch(i))
675 node->setChild(i,
nullptr);
679 prevNode = std::make_shared<SHAMapTreeNode>(
680 item, type, node->getSeq());
684 prevNode = std::move(node);
690 prevNode = std::move(node);
717 Throw<SHAMapMissingNode>(
type_, tag);
719 auto [node, nodeID] = stack.
top();
724 auto leaf = std::static_pointer_cast<SHAMapTreeNode>(node);
725 if (leaf->peekItem()->key() == tag)
732 auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
733 int branch = nodeID.selectBranch(tag);
734 assert(inner->isEmptyBranch(branch));
735 auto newNode = std::make_shared<SHAMapTreeNode>(item, type,
seq_);
736 inner->setChild(branch, newNode);
742 auto leaf = std::static_pointer_cast<SHAMapTreeNode>(node);
744 assert(otherItem && (tag != otherItem->key()));
746 node = std::make_shared<SHAMapInnerNode>(node->getSeq());
750 while ((b1 = nodeID.selectBranch(tag)) ==
751 (b2 = nodeID.selectBranch(otherItem->key())))
753 stack.
push({node, nodeID});
757 nodeID = nodeID.getChildNodeID(b1);
758 node = std::make_shared<SHAMapInnerNode>(
seq_);
762 assert(node->isInner());
765 std::make_shared<SHAMapTreeNode>(item, type,
seq_);
766 assert(newNode->isValid() && newNode->isLeaf());
767 auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
768 inner->setChild(b1, newNode);
770 newNode = std::make_shared<SHAMapTreeNode>(otherItem, type,
seq_);
771 assert(newNode->isValid() && newNode->isLeaf());
772 inner->setChild(b2, newNode);
783 std::make_shared<SHAMapItem const>(std::move(i)),
791 auto hash =
root_->getNodeHash();
795 hash =
root_->getNodeHash();
815 Throw<SHAMapMissingNode>(
type_, tag);
817 auto node = std::dynamic_pointer_cast<SHAMapTreeNode>(stack.
top().
first);
821 if (!node || (node->peekItem()->key() != tag))
846 if (hash ==
root_->getNodeHash())
853 stream <<
"Fetch root TXN node " << hash;
857 stream <<
"Fetch root STATE node " << hash;
861 stream <<
"Fetch root SHAMap node " << hash;
870 assert(
root_->getNodeHash() == hash);
893 assert(node->getSeq() ==
seq_);
904 node->getNodeHash().as_uint256(),
912 template <
class Node>
918 assert(node->getSeq() != 0);
920 if (node->getSeq() !=
seq_)
924 node = std::static_pointer_cast<Node>(node->clone(
seq_));
964 auto node = std::static_pointer_cast<SHAMapInnerNode>(
root_);
968 root_ = std::make_shared<SHAMapInnerNode>(0);
986 if (node->isEmptyBranch(pos))
995 auto child = node->getChild(pos++);
997 if (child && (child->getSeq() != 0))
1003 if (child->isInner())
1007 stack.
emplace(std::move(node), branch);
1009 node = std::static_pointer_cast<SHAMapInnerNode>(
1018 assert(node->getSeq() ==
seq_);
1019 child->updateHash();
1022 child =
writeNode(t, seq, std::move(child));
1026 node->shareChild(branch, child);
1033 node->updateHashDeep();
1037 node = std::static_pointer_cast<SHAMapInnerNode>(
1047 auto parent = std::move(stack.
top().first);
1048 pos = stack.
top().second;
1052 assert(parent->getSeq() ==
seq_);
1053 parent->shareChild(pos, node);
1056 node = std::move(parent);
1061 root_ = std::move(node);
1077 auto [node, nodeID] = stack.
top();
1083 JLOG(
journal_.
info()) <<
"Hash: " << node->getNodeHash();
1086 if (node->isInner())
1089 for (
int i = 0; i < 16; ++i)
1091 if (!inner->isEmptyBranch(i))
1093 auto child = inner->getChildPointer(i);
1096 assert(child->getNodeHash() == inner->getChildHash(i));
1097 stack.
push({child, nodeID.getChildNodeID(i)});
1104 }
while (!stack.
empty());
1106 JLOG(
journal_.
info()) << leafCount <<
" resident leaves";
1113 assert(!ret || !ret->getSeq());
1123 assert(node->getSeq() == 0);
1124 assert(node->getNodeHash() == hash);
1133 auto node =
root_.get();
1134 assert(node !=
nullptr);
1135 assert(!node->isLeaf());
1140 node->invariants(
true);