diff --git a/src/SHAMap.cpp b/src/SHAMap.cpp index 7bb86ac30..85bbf3a61 100644 --- a/src/SHAMap.cpp +++ b/src/SHAMap.cpp @@ -814,6 +814,38 @@ SHAMapTreeNode::pointer SHAMap::getNode(const SHAMapNode& nodeID) return node; } +bool SHAMap::getPath(const uint256& index, std::vector< std::vector >& nodes, SHANodeFormat format) +{ + // Return the path of nodes to the specified index in the specified format + // Return value: true = node present, false = node not present + + boost::recursive_mutex::scoped_lock sl(mLock); + SHAMapTreeNode* inNode = root.get(); + + while (!inNode->isLeaf()) + { + Serializer s; + inNode->addRaw(s, format); + nodes.push_back(s.peekData()); + + int branch = inNode->selectBranch(index); + if (inNode->isEmptyBranch(branch)) // paths leads to empty branch + return false; + inNode = getNodePointer(inNode->getChildNodeID(branch), inNode->getChildHash(branch)); + if (!inNode) + throw SHAMapMissingNode(mType, inNode->getChildNodeID(branch), inNode->getChildHash(branch), index); + } + + if (inNode->getTag() != index) // path leads to different leaf + return false; + + // path lead to the requested leaf + Serializer s; + inNode->addRaw(s, format); + nodes.push_back(s.peekData()); + return true; +} + void SHAMap::dump(bool hash) { #if 0 diff --git a/src/SHAMap.h b/src/SHAMap.h index 2518669b2..7426ab780 100644 --- a/src/SHAMap.h +++ b/src/SHAMap.h @@ -125,6 +125,7 @@ enum SHANodeFormat { snfPREFIX = 1, // Form that hashes to its official hash snfWIRE = 2, // Compressed form used on the wire + snfHASH = 3, // just the hash }; enum SHAMapType @@ -404,6 +405,8 @@ public: void walkMap(std::vector& missingNodes, int maxMissing); + bool getPath(const uint256& index, std::vector< std::vector >& nodes, SHANodeFormat format); + bool deepCompare(SHAMap& other); virtual void dump(bool withHashes = false); }; diff --git a/src/SHAMapNodes.cpp b/src/SHAMapNodes.cpp index b14516813..b301e9db8 100644 --- a/src/SHAMapNodes.cpp +++ b/src/SHAMapNodes.cpp @@ -259,7 +259,7 @@ SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& id, const std::vector(mHashes), sizeof(mHashes)); +#ifdef DEBUG + Serializer s; + s.add32(sHP_InnerNode); + for(int i = 0; i < 16; ++i) + s.add256(mHashes[i]); + assert(nh == s.getSHA512Half()); +#endif + } } else if (mType == tnTRANSACTION_NM) { @@ -366,11 +381,15 @@ bool SHAMapTreeNode::updateHash() void SHAMapTreeNode::addRaw(Serializer& s, SHANodeFormat format) { - assert((format == snfPREFIX) || (format == snfWIRE)); + assert((format == snfPREFIX) || (format == snfWIRE) || (format == snfHASH)); if (mType == tnERROR) throw std::runtime_error("invalid I node type"); - if (mType == tnINNER) + if (format == snfHASH) + { + s.add256(getNodeHash()); + } + else if (mType == tnINNER) { assert(!isEmpty()); if (format == snfPREFIX)