diff --git a/src/ripple/shamap/SHAMap.h b/src/ripple/shamap/SHAMap.h index dc56d6d91..b94ef668e 100644 --- a/src/ripple/shamap/SHAMap.h +++ b/src/ripple/shamap/SHAMap.h @@ -269,13 +269,6 @@ SHAMap::setLedgerSeq (std::uint32_t lseq) ledgerSeq_ = lseq; } -inline -uint256 -SHAMap::getHash () const -{ - return root_->getNodeHash (); -} - inline void SHAMap::setImmutable () diff --git a/src/ripple/shamap/SHAMapTreeNode.h b/src/ripple/shamap/SHAMapTreeNode.h index 076fcd4cb..ec618991f 100644 --- a/src/ripple/shamap/SHAMapTreeNode.h +++ b/src/ripple/shamap/SHAMapTreeNode.h @@ -77,8 +77,7 @@ public: uint256 const& getNodeHash () const; public: // public only to SHAMap - bool setChild (int m, uint256 const& hash, - std::shared_ptr const& child); + void setChild (int m, std::shared_ptr const& child); void shareChild (int m, std::shared_ptr const& child); // node functions @@ -118,12 +117,13 @@ public: // public only to SHAMap void dump (SHAMapNodeID const&, beast::Journal journal); #endif std::string getString (SHAMapNodeID const&) const; + bool updateHash (); + void updateHashDeep(); private: bool isTransaction () const; bool hasMetaData () const; bool isAccountState () const; - bool updateHash (); }; inline diff --git a/src/ripple/shamap/impl/SHAMap.cpp b/src/ripple/shamap/impl/SHAMap.cpp index fd11abae0..e043e5662 100644 --- a/src/ripple/shamap/impl/SHAMap.cpp +++ b/src/ripple/shamap/impl/SHAMap.cpp @@ -137,14 +137,7 @@ SHAMap::dirtyUp (SharedPtrNodeStack& stack, assert (branch >= 0); unshareNode (node, nodeID); - - if (! node->setChild (branch, child->getNodeHash(), child)) - { - journal_.fatal << - "dirtyUp terminates early"; - assert (false); - return; - } + node->setChild (branch, child); #ifdef ST_DEBUG if (journal_.trace) journal_.trace << @@ -701,11 +694,7 @@ bool SHAMap::delItem (uint256 const& id) assert (node->isInner ()); unshareNode (node, nodeID); - if (! node->setChild (nodeID.selectBranch (id), prevHash, prevNode)) - { - assert (false); - return true; - } + node->setChild (nodeID.selectBranch (id), prevNode); if (!nodeID.isRoot ()) { @@ -730,10 +719,7 @@ bool SHAMap::delItem (uint256 const& id) { if (!node->isEmptyBranch (i)) { - if (! node->setChild (i, uint256(), nullptr)) - { - assert (false); - } + node->setChild (i, nullptr); break; } } @@ -742,14 +728,12 @@ bool SHAMap::delItem (uint256 const& id) prevHash = node->getNodeHash (); prevNode = std::move (node); - assert (prevHash.isNonZero ()); } else { // This node is now the end of the branch prevHash = node->getNodeHash (); prevNode = std::move (node); - assert (prevHash.isNonZero ()); } } } @@ -787,10 +771,7 @@ SHAMap::addGiveItem (std::shared_ptr const& item, int branch = nodeID.selectBranch (tag); assert (node->isEmptyBranch (branch)); auto newNode = std::make_shared (item, type, seq_); - if (! node->setChild (branch, newNode->getNodeHash (), newNode)) - { - assert (false); - } + node->setChild (branch, newNode); } else { @@ -819,17 +800,11 @@ SHAMap::addGiveItem (std::shared_ptr const& item, std::shared_ptr newNode = std::make_shared (item, type, seq_); assert (newNode->isValid () && newNode->isLeaf ()); - if (!node->setChild (b1, newNode->getNodeHash (), newNode)) - { - assert (false); - } + node->setChild (b1, newNode); newNode = std::make_shared (otherItem, type, seq_); assert (newNode->isValid () && newNode->isLeaf ()); - if (!node->setChild (b2, newNode->getNodeHash (), newNode)) - { - assert (false); - } + node->setChild (b2, newNode); } dirtyUp (stack, tag, node); @@ -841,6 +816,18 @@ bool SHAMap::addItem (const SHAMapItem& i, bool isTransaction, bool hasMetaData) return addGiveItem (std::make_shared (i), isTransaction, hasMetaData); } +uint256 +SHAMap::getHash () const +{ + auto hash = root_->getNodeHash(); + if (hash.isZero()) + { + const_cast(*this).unshare(); + hash = root_->getNodeHash(); + } + return hash; +} + bool SHAMap::updateGiveItem (std::shared_ptr const& item, bool isTransaction, bool hasMeta) @@ -1034,6 +1021,7 @@ SHAMap::walkSubTree (bool doWrite, NodeObjectType t, std::uint32_t seq) preFlushNode (child); assert (node->getSeq() == seq_); + child->updateHash(); if (doWrite && backed_) writeNode (t, seq, child); @@ -1044,6 +1032,9 @@ SHAMap::walkSubTree (bool doWrite, NodeObjectType t, std::uint32_t seq) } } + // update the hash of this inner node + node->updateHashDeep(); + // This inner node can now be shared if (doWrite && backed_) writeNode (t, seq, node); diff --git a/src/ripple/shamap/impl/SHAMapTreeNode.cpp b/src/ripple/shamap/impl/SHAMapTreeNode.cpp index 7ee7fcf5f..2e9f6ccf6 100644 --- a/src/ripple/shamap/impl/SHAMapTreeNode.cpp +++ b/src/ripple/shamap/impl/SHAMapTreeNode.cpp @@ -310,6 +310,17 @@ bool SHAMapTreeNode::updateHash () return true; } +void +SHAMapTreeNode::updateHashDeep() +{ + for (auto pos = 0; pos < 16; ++pos) + { + if (mChildren[pos] != nullptr) + mHashes[pos] = mChildren[pos]->mHash; + } + updateHash(); +} + void SHAMapTreeNode::addRaw (Serializer& s, SHANodeFormat format) { assert ((format == snfPREFIX) || (format == snfWIRE) || (format == snfHASH)); @@ -490,32 +501,20 @@ std::string SHAMapTreeNode::getString (const SHAMapNodeID & id) const } // We are modifying an inner node -bool SHAMapTreeNode::setChild (int m, uint256 const& hash, std::shared_ptr const& child) +void +SHAMapTreeNode::setChild (int m, std::shared_ptr const& child) { assert ((m >= 0) && (m < 16)); assert (mType == tnINNER); assert (mSeq != 0); assert (child.get() != this); - - if (mHashes[m] == hash) - return false; - - mHashes[m] = hash; - - if (hash.isNonZero ()) - { - assert (child && (child->getNodeHash() == hash)); + mHashes[m].zero(); + mHash.zero(); + if (child) mIsBranch |= (1 << m); - } else - { - assert (!child); mIsBranch &= ~ (1 << m); - } - mChildren[m] = child; - - return updateHash (); } // finished modifying, now make shareable @@ -526,7 +525,6 @@ void SHAMapTreeNode::shareChild (int m, std::shared_ptr const& c assert (mSeq != 0); assert (child); assert (child.get() != this); - assert (child->getNodeHash() == mHashes[m]); mChildren[m] = child; } @@ -546,7 +544,6 @@ std::shared_ptr SHAMapTreeNode::getChild (int branch) assert (isInnerNode ()); std::unique_lock lock (childLock); - assert (!mChildren[branch] || (mHashes[branch] == mChildren[branch]->getNodeHash())); return mChildren[branch]; }