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();
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));
736 std::make_shared<SHAMapTreeNode>(std::move(item), type,
seq_);
737 inner->setChild(branch, newNode);
743 auto leaf = std::static_pointer_cast<SHAMapTreeNode>(node);
745 assert(otherItem && (tag != otherItem->key()));
747 node = std::make_shared<SHAMapInnerNode>(node->getSeq());
751 while ((b1 = nodeID.selectBranch(tag)) ==
752 (b2 = nodeID.selectBranch(otherItem->key())))
754 stack.
push({node, nodeID});
758 nodeID = nodeID.getChildNodeID(b1);
759 node = std::make_shared<SHAMapInnerNode>(
seq_);
763 assert(node->isInner());
766 std::make_shared<SHAMapTreeNode>(std::move(item), type,
seq_);
767 assert(newNode->isValid() && newNode->isLeaf());
768 auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
769 inner->setChild(b1, newNode);
772 std::make_shared<SHAMapTreeNode>(std::move(otherItem), type,
seq_);
773 assert(newNode->isValid() && newNode->isLeaf());
774 inner->setChild(b2, newNode);
785 std::make_shared<SHAMapItem const>(std::move(i)),
793 auto hash =
root_->getNodeHash();
797 hash =
root_->getNodeHash();
817 Throw<SHAMapMissingNode>(
type_, tag);
819 auto node = std::dynamic_pointer_cast<SHAMapTreeNode>(stack.
top().
first);
823 if (!node || (node->peekItem()->key() != tag))
848 if (hash ==
root_->getNodeHash())
855 stream <<
"Fetch root TXN node " << hash;
859 stream <<
"Fetch root STATE node " << hash;
863 stream <<
"Fetch root SHAMap node " << hash;
872 assert(
root_->getNodeHash() == hash);
895 assert(node->getSeq() ==
seq_);
906 node->getNodeHash().as_uint256(),
914 template <
class Node>
920 assert(node->getSeq() != 0);
922 if (node->getSeq() !=
seq_)
926 node = std::static_pointer_cast<Node>(node->clone(
seq_));
966 auto node = std::static_pointer_cast<SHAMapInnerNode>(
root_);
970 root_ = std::make_shared<SHAMapInnerNode>(0);
988 if (node->isEmptyBranch(pos))
997 auto child = node->getChild(pos++);
999 if (child && (child->getSeq() != 0))
1005 if (child->isInner())
1009 stack.
emplace(std::move(node), branch);
1013 node = std::static_pointer_cast<SHAMapInnerNode>(
1022 assert(node->getSeq() ==
seq_);
1023 child->updateHash();
1026 child =
writeNode(t, seq, std::move(child));
1030 node->shareChild(branch, child);
1037 node->updateHashDeep();
1041 node = std::static_pointer_cast<SHAMapInnerNode>(
1051 auto parent = std::move(stack.
top().first);
1052 pos = stack.
top().second;
1056 assert(parent->getSeq() ==
seq_);
1057 parent->shareChild(pos, node);
1060 node = std::move(parent);
1065 root_ = std::move(node);
1081 auto [node, nodeID] = stack.
top();
1087 JLOG(
journal_.
info()) <<
"Hash: " << node->getNodeHash();
1090 if (node->isInner())
1093 for (
int i = 0; i < 16; ++i)
1095 if (!inner->isEmptyBranch(i))
1097 auto child = inner->getChildPointer(i);
1100 assert(child->getNodeHash() == inner->getChildHash(i));
1101 stack.
push({child, nodeID.getChildNodeID(i)});
1108 }
while (!stack.
empty());
1110 JLOG(
journal_.
info()) << leafCount <<
" resident leaves";
1117 assert(!ret || !ret->getSeq());
1127 assert(node->getSeq() == 0);
1128 assert(node->getNodeHash() == hash);
1131 ->canonicalize_replace_client(hash.
as_uint256(), node);
1138 auto node =
root_.get();
1139 assert(node !=
nullptr);
1140 assert(!node->isLeaf());
1145 node->invariants(
true);