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)
168 const_cast<bool&
>(
full_) =
false;
179 if (
auto nodeData = filter->
getNode(hash))
191 std::move(*nodeData),
201 <<
"Invalid node/data, hash=" << hash <<
": " << x.
what();
250 Throw<SHAMapMissingNode>(
type_, hash);
272 if (!ret && !parent->isEmptyBranch(branch))
273 Throw<SHAMapMissingNode>(
type_, parent->getChildHash(branch));
302 node =
fetchNode(parent->getChildHash(branch));
306 node = parent->canonicalizeChild(branch, std::move(node));
319 ret =
fetchNode(parent->getChildHash(branch));
331 assert((branch >= 0) && (branch < 16));
345 child = childNode.
get();
397 template <
class Node>
402 assert(node->isValid());
403 assert(node->getSeq() <=
seq_);
404 if (node->getSeq() !=
seq_)
408 node = std::static_pointer_cast<Node>(node->clone(
seq_));
409 assert(node->isValid());
425 auto n = std::static_pointer_cast<SHAMapTreeNode>(node);
426 stack.
push({node, {64, n->peekItem()->key()}});
429 auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
433 stack.
push({inner, stack.
top().second.getChildNodeID(branch)});
434 for (
int i = 0; i < 16;)
436 if (!inner->isEmptyBranch(i))
439 assert(!stack.
empty());
442 auto n = std::static_pointer_cast<SHAMapTreeNode>(node);
443 stack.
push({n, {64, n->peekItem()->key()}});
446 inner = std::static_pointer_cast<SHAMapInnerNode>(node);
447 stack.
push({inner, stack.
top().second.getChildNodeID(branch)});
467 for (
int i = 0; i < 16; ++i)
469 if (!inner->isEmptyBranch(i))
490 assert(leaf->hasItem() || (leaf ==
root_.get()));
492 return leaf->peekItem();
500 assert(stack.
empty());
504 while (!stack.
empty())
514 assert(!stack.
empty());
515 assert(stack.
top().
first->isLeaf());
517 while (!stack.
empty())
519 auto [node, nodeID] = stack.
top();
520 assert(!node->isLeaf());
521 auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
522 for (
auto i = nodeID.selectBranch(
id) + 1; i < 16; ++i)
524 if (!inner->isEmptyBranch(i))
529 Throw<SHAMapMissingNode>(
type_,
id);
530 assert(leaf->isLeaf());
582 while (!stack.
empty())
584 auto [node, nodeID] = stack.
top();
588 if (leaf->peekItem()->key() > id)
590 this, leaf->peekItem().get(), std::move(stack));
594 auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
595 for (
auto branch = nodeID.selectBranch(
id) + 1; branch < 16;
598 if (!inner->isEmptyBranch(branch))
603 Throw<SHAMapMissingNode>(
type_,
id);
605 this, leaf->peekItem().get(), std::move(stack));
619 return (leaf !=
nullptr);
632 Throw<SHAMapMissingNode>(
type_,
id);
634 auto leaf = std::dynamic_pointer_cast<SHAMapTreeNode>(stack.
top().
first);
637 if (!leaf || (leaf->peekItem()->key() !=
id))
646 while (!stack.
empty())
649 std::static_pointer_cast<SHAMapInnerNode>(stack.
top().
first);
660 const int bc = node->getBranchCount();
673 for (
int i = 0; i < 16; ++i)
675 if (!node->isEmptyBranch(i))
677 node->setChild(i,
nullptr);
681 prevNode = std::make_shared<SHAMapTreeNode>(
682 item, type, node->getSeq());
686 prevNode = std::move(node);
692 prevNode = std::move(node);
719 Throw<SHAMapMissingNode>(
type_, tag);
721 auto [node, nodeID] = stack.
top();
726 auto leaf = std::static_pointer_cast<SHAMapTreeNode>(node);
727 if (leaf->peekItem()->key() == tag)
734 auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
735 int branch = nodeID.selectBranch(tag);
736 assert(inner->isEmptyBranch(branch));
738 std::make_shared<SHAMapTreeNode>(std::move(item), type,
seq_);
739 inner->setChild(branch, newNode);
745 auto leaf = std::static_pointer_cast<SHAMapTreeNode>(node);
747 assert(otherItem && (tag != otherItem->key()));
749 node = std::make_shared<SHAMapInnerNode>(node->getSeq());
753 while ((b1 = nodeID.selectBranch(tag)) ==
754 (b2 = nodeID.selectBranch(otherItem->key())))
756 stack.
push({node, nodeID});
760 nodeID = nodeID.getChildNodeID(b1);
761 node = std::make_shared<SHAMapInnerNode>(
seq_);
765 assert(node->isInner());
768 std::make_shared<SHAMapTreeNode>(std::move(item), type,
seq_);
769 assert(newNode->isValid() && newNode->isLeaf());
770 auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
771 inner->setChild(b1, newNode);
774 std::make_shared<SHAMapTreeNode>(std::move(otherItem), type,
seq_);
775 assert(newNode->isValid() && newNode->isLeaf());
776 inner->setChild(b2, newNode);
787 std::make_shared<SHAMapItem const>(std::move(i)),
795 auto hash =
root_->getNodeHash();
799 hash =
root_->getNodeHash();
819 Throw<SHAMapMissingNode>(
type_, tag);
821 auto node = std::dynamic_pointer_cast<SHAMapTreeNode>(stack.
top().
first);
825 if (!node || (node->peekItem()->key() != tag))
850 if (hash ==
root_->getNodeHash())
857 stream <<
"Fetch root TXN node " << hash;
861 stream <<
"Fetch root STATE node " << hash;
865 stream <<
"Fetch root SHAMap node " << hash;
874 assert(
root_->getNodeHash() == hash);
897 assert(node->getSeq() ==
seq_);
908 node->getNodeHash().as_uint256(),
916 template <
class Node>
922 assert(node->getSeq() != 0);
924 if (node->getSeq() !=
seq_)
928 node = std::static_pointer_cast<Node>(node->clone(
seq_));
968 auto node = std::static_pointer_cast<SHAMapInnerNode>(
root_);
972 root_ = std::make_shared<SHAMapInnerNode>(0);
990 if (node->isEmptyBranch(pos))
999 auto child = node->getChild(pos++);
1001 if (child && (child->getSeq() != 0))
1007 if (child->isInner())
1011 stack.
emplace(std::move(node), branch);
1015 node = std::static_pointer_cast<SHAMapInnerNode>(
1024 assert(node->getSeq() ==
seq_);
1025 child->updateHash();
1028 child =
writeNode(t, seq, std::move(child));
1032 node->shareChild(branch, child);
1039 node->updateHashDeep();
1043 node = std::static_pointer_cast<SHAMapInnerNode>(
1053 auto parent = std::move(stack.
top().first);
1054 pos = stack.
top().second;
1058 assert(parent->getSeq() ==
seq_);
1059 parent->shareChild(pos, node);
1062 node = std::move(parent);
1067 root_ = std::move(node);
1083 auto [node, nodeID] = stack.
top();
1089 JLOG(
journal_.
info()) <<
"Hash: " << node->getNodeHash();
1092 if (node->isInner())
1095 for (
int i = 0; i < 16; ++i)
1097 if (!inner->isEmptyBranch(i))
1099 auto child = inner->getChildPointer(i);
1102 assert(child->getNodeHash() == inner->getChildHash(i));
1103 stack.
push({child, nodeID.getChildNodeID(i)});
1110 }
while (!stack.
empty());
1112 JLOG(
journal_.
info()) << leafCount <<
" resident leaves";
1119 assert(!ret || !ret->getSeq());
1129 assert(node->getSeq() == 0);
1130 assert(node->getNodeHash() == hash);
1133 ->canonicalize_replace_client(hash.
as_uint256(), node);
1140 auto node =
root_.get();
1141 assert(node !=
nullptr);
1142 assert(!node->isLeaf());
1147 node->invariants(
true);