20 #include <ripple/basics/contract.h>
21 #include <ripple/shamap/SHAMap.h>
27 , journal_(f.journal())
32 root_ = std::make_shared<SHAMapInnerNode>(
seq_);
41 , journal_(f.journal())
46 root_ = std::make_shared<SHAMapInnerNode>(
seq_);
57 auto ret = std::make_shared<SHAMap>(
type_,
f_);
92 assert(child && (child->getSeq() ==
seq_));
94 while (!stack.
empty())
97 std::dynamic_pointer_cast<SHAMapInnerNode>(stack.
top().
first);
100 assert(node !=
nullptr);
106 node->setChild(branch, child);
108 child = std::move(node);
115 assert(stack ==
nullptr || stack->
empty());
119 while (inNode->isInner())
121 if (stack !=
nullptr)
122 stack->
push({inNode, nodeID});
124 auto const inner = std::static_pointer_cast<SHAMapInnerNode>(inNode);
126 if (inner->isEmptyBranch(branch))
133 if (stack !=
nullptr)
134 stack->
push({inNode, nodeID});
142 if (leaf && leaf->
peekItem()->key() !=
id)
172 const_cast<bool&
>(
full_) =
false;
183 if (
auto nodeData = filter->
getNode(hash))
195 std::move(*nodeData),
205 <<
"Invalid node/data, hash=" << hash <<
": " << x.
what();
254 Throw<SHAMapMissingNode>(
type_, hash);
276 if (!ret && !parent->isEmptyBranch(branch))
277 Throw<SHAMapMissingNode>(
type_, parent->getChildHash(branch));
306 node =
fetchNode(parent->getChildHash(branch));
310 node = parent->canonicalizeChild(branch, std::move(node));
323 ret =
fetchNode(parent->getChildHash(branch));
335 assert((branch >= 0) && (branch < 16));
349 child = childNode.
get();
401 template <
class Node>
406 assert(node->isValid());
407 assert(node->getSeq() <=
seq_);
408 if (node->getSeq() !=
seq_)
412 node = std::static_pointer_cast<Node>(node->clone(
seq_));
413 assert(node->isValid());
429 auto n = std::static_pointer_cast<SHAMapTreeNode>(node);
430 stack.
push({node, {64, n->peekItem()->key()}});
433 auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
437 stack.
push({inner, stack.
top().second.getChildNodeID(branch)});
438 for (
int i = 0; i < 16;)
440 if (!inner->isEmptyBranch(i))
443 assert(!stack.
empty());
446 auto n = std::static_pointer_cast<SHAMapTreeNode>(node);
447 stack.
push({n, {64, n->peekItem()->key()}});
450 inner = std::static_pointer_cast<SHAMapInnerNode>(node);
451 stack.
push({inner, stack.
top().second.getChildNodeID(branch)});
471 for (
int i = 0; i < 16; ++i)
473 if (!inner->isEmptyBranch(i))
494 assert(leaf->hasItem() || (leaf ==
root_.get()));
496 return leaf->peekItem();
502 assert(stack.
empty());
506 while (!stack.
empty())
516 assert(!stack.
empty());
517 assert(stack.
top().
first->isLeaf());
519 while (!stack.
empty())
521 auto [node, nodeID] = stack.
top();
522 assert(!node->isLeaf());
523 auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
524 for (
auto i = nodeID.selectBranch(
id) + 1; i < 16; ++i)
526 if (!inner->isEmptyBranch(i))
531 Throw<SHAMapMissingNode>(
type_,
id);
532 assert(leaf->isLeaf());
584 while (!stack.
empty())
586 auto [node, nodeID] = stack.
top();
590 if (leaf->peekItem()->key() > id)
592 this, leaf->peekItem().get(), std::move(stack));
596 auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
597 for (
auto branch = nodeID.selectBranch(
id) + 1; branch < 16;
600 if (!inner->isEmptyBranch(branch))
605 Throw<SHAMapMissingNode>(
type_,
id);
607 this, leaf->peekItem().get(), std::move(stack));
621 return (leaf !=
nullptr);
634 Throw<SHAMapMissingNode>(
type_,
id);
636 auto leaf = std::dynamic_pointer_cast<SHAMapTreeNode>(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();
675 for (
int i = 0; i < 16; ++i)
677 if (!node->isEmptyBranch(i))
679 node->setChild(i,
nullptr);
683 prevNode = std::make_shared<SHAMapTreeNode>(
684 item, type, node->getSeq());
688 prevNode = std::move(node);
694 prevNode = std::move(node);
721 Throw<SHAMapMissingNode>(
type_, tag);
723 auto [node, nodeID] = stack.
top();
728 auto leaf = std::static_pointer_cast<SHAMapTreeNode>(node);
729 if (leaf->peekItem()->key() == tag)
736 auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
737 int branch = nodeID.selectBranch(tag);
738 assert(inner->isEmptyBranch(branch));
740 std::make_shared<SHAMapTreeNode>(std::move(item), type,
seq_);
741 inner->setChild(branch, newNode);
747 auto leaf = std::static_pointer_cast<SHAMapTreeNode>(node);
749 assert(otherItem && (tag != otherItem->key()));
751 node = std::make_shared<SHAMapInnerNode>(node->getSeq());
755 while ((b1 = nodeID.selectBranch(tag)) ==
756 (b2 = nodeID.selectBranch(otherItem->key())))
758 stack.
push({node, nodeID});
762 nodeID = nodeID.getChildNodeID(b1);
763 node = std::make_shared<SHAMapInnerNode>(
seq_);
767 assert(node->isInner());
770 std::make_shared<SHAMapTreeNode>(std::move(item), type,
seq_);
771 assert(newNode->isValid() && newNode->isLeaf());
772 auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
773 inner->setChild(b1, newNode);
776 std::make_shared<SHAMapTreeNode>(std::move(otherItem), type,
seq_);
777 assert(newNode->isValid() && newNode->isLeaf());
778 inner->setChild(b2, newNode);
789 std::make_shared<SHAMapItem const>(std::move(i)),
797 auto hash =
root_->getNodeHash();
801 hash =
root_->getNodeHash();
821 Throw<SHAMapMissingNode>(
type_, tag);
823 auto node = std::dynamic_pointer_cast<SHAMapTreeNode>(stack.
top().
first);
827 if (!node || (node->peekItem()->key() != tag))
852 if (hash ==
root_->getNodeHash())
859 stream <<
"Fetch root TXN node " << hash;
863 stream <<
"Fetch root STATE node " << hash;
867 stream <<
"Fetch root SHAMap node " << hash;
876 assert(
root_->getNodeHash() == hash);
899 assert(node->getSeq() ==
seq_);
910 node->getNodeHash().as_uint256(),
918 template <
class Node>
924 assert(node->getSeq() != 0);
926 if (node->getSeq() !=
seq_)
930 node = std::static_pointer_cast<Node>(node->clone(
seq_));
970 auto node = std::static_pointer_cast<SHAMapInnerNode>(
root_);
974 root_ = std::make_shared<SHAMapInnerNode>(0);
992 if (node->isEmptyBranch(pos))
1001 auto child = node->getChild(pos++);
1003 if (child && (child->getSeq() != 0))
1009 if (child->isInner())
1013 stack.
emplace(std::move(node), branch);
1017 node = std::static_pointer_cast<SHAMapInnerNode>(
1026 assert(node->getSeq() ==
seq_);
1027 child->updateHash();
1030 child =
writeNode(t, seq, std::move(child));
1034 node->shareChild(branch, child);
1041 node->updateHashDeep();
1045 node = std::static_pointer_cast<SHAMapInnerNode>(
1055 auto parent = std::move(stack.
top().first);
1056 pos = stack.
top().second;
1060 assert(parent->getSeq() ==
seq_);
1061 parent->shareChild(pos, node);
1064 node = std::move(parent);
1069 root_ = std::move(node);
1085 auto [node, nodeID] = stack.
top();
1091 JLOG(
journal_.
info()) <<
"Hash: " << node->getNodeHash();
1094 if (node->isInner())
1097 for (
int i = 0; i < 16; ++i)
1099 if (!inner->isEmptyBranch(i))
1101 auto child = inner->getChildPointer(i);
1104 assert(child->getNodeHash() == inner->getChildHash(i));
1105 stack.
push({child, nodeID.getChildNodeID(i)});
1112 }
while (!stack.
empty());
1114 JLOG(
journal_.
info()) << leafCount <<
" resident leaves";
1121 assert(!ret || !ret->getSeq());
1131 assert(node->getSeq() == 0);
1132 assert(node->getNodeHash() == hash);
1135 ->canonicalize_replace_client(hash.
as_uint256(), node);
1142 auto node =
root_.get();
1143 assert(node !=
nullptr);
1144 assert(!node->isLeaf());
1149 node->invariants(
true);