diff --git a/SHAMap.cpp b/SHAMap.cpp index e3acabe0b4..a9d3af94ef 100644 --- a/SHAMap.cpp +++ b/SHAMap.cpp @@ -1,87 +1,131 @@ #include "BitcoinUtil.h" #include "SHAMap.h" +#include -bool SHAMapNodeID::operator<(const SHAMapNodeID &s) const +bool SHAMapNode::operator<(const SHAMapNode &s) const { - if(s.mDepthmDepth) return false; - return mNodeIDmDepth) return false; + return mNodeID(const SHAMapNodeID &s) const +bool SHAMapNode::operator>(const SHAMapNode &s) const { - if(s.mDepthmDepth) return true; - return mNodeID>s.mNodeID; + if(s.mDepthmDepth) return true; + return mNodeID>s.mNodeID; } -bool SHAMapNodeID::operator<=(const SHAMapNodeID &s) const +bool SHAMapNode::operator<=(const SHAMapNode &s) const { - if(s.mDepthmDepth) return false; - return mNodeID<=s.mNodeID; + if(s.mDepthmDepth) return false; + return mNodeID<=s.mNodeID; } -bool SHAMapNodeID::operator>=(const SHAMapNodeID &s) const +bool SHAMapNode::operator>=(const SHAMapNode &s) const { - if(s.mDepthmDepth) return true; - return mNodeID>=s.mNodeID; + if(s.mDepthmDepth) return true; + return mNodeID>=s.mNodeID; } -bool SHAMapNodeID::operator==(const SHAMapNodeID &s) const +bool SHAMapNode::operator==(const SHAMapNode &s) const { - return (s.mDepth==mDepth) && (s.mNodeID==mNodeID); + return (s.mDepth==mDepth) && (s.mNodeID==mNodeID); } -bool SHAMapNodeID::operator!=(const SHAMapNodeID &s) const +bool SHAMapNode::operator!=(const SHAMapNode &s) const { - return (s.mDepth!=mDepth) || (s.mNodeID!=mNodeID); + return (s.mDepth!=mDepth) || (s.mNodeID!=mNodeID); } -void SHAMapNodeID::ClassInit() +void SHAMapNode::ClassInit() { - int i; - char HexBuf[65]; + int i; + char HexBuf[65]; - for(i=0; i<64; i++) HexBuf[i]='0'; - HexBuf[64]=0; - for(i=0; i=0 && depth=0 && depth>=(mDepth*8); + uint256 branch=m; + branch>>=(mDepth*8); - return SHAMapNodeID(mDepth+1, mNodeID | branch); + return SHAMapNode(mDepth+1, mNodeID | branch); } -int SHAMapNodeID::selectBranch(const uint256 &hash) +int SHAMapNode::selectBranch(const uint256 &hash) { - if(isLeaf()) // no nodes under this node - return -1; - if((hash&smMasks[mDepth])!=mNodeID) - return -1; // does not go under this node + if(isLeaf()) // no nodes under this node + return -1; + if((hash&smMasks[mDepth])!=mNodeID) + return -1; // does not go under this node - uint256 selector=hash&smMasks[mDepth+1]; - int branch=*(selector.begin()+mDepth); + uint256 selector=hash&smMasks[mDepth+1]; + int branch=*(selector.begin()+mDepth); - assert(branch>=0 && branch<32); - return branch; + assert(branch>=0 && branch<32); + return branch; } +SHAMapLeafNode::SHAMapLeafNode(const SHAMapNode& nodeID) : SHAMapNode(nodeID), mHash(0) +{ + ; +} + +void SHAMapLeafNode::updateHash(void) +{ +} + +bool SHAMapLeafNode::hasHash(const uint256& hash) const +{ + BOOST_FOREACH(const uint256& entry, mHashes) + if(entry==hash) return true; + return false; +} + +bool SHAMapLeafNode::addHash(const uint256& hash) +{ // The node will almost never have more than one hash in it + std::list::iterator it; + for(it=mHashes.begin(); it!=mHashes.end(); it++) + { + if(*it==hash) return false; + if(*it>hash) break; + } + mHashes.insert(it, hash); + updateHash(); + return true; +} + +bool SHAMapLeafNode::delHash(const uint256& hash) +{ + std::list::iterator it; + for(it=mHashes.begin(); it!=mHashes.end(); it++) + { + if(*it==hash) + { + mHashes.erase(it); + updateHash(); + return true; + } + } + return false; +} diff --git a/SHAMap.h b/SHAMap.h index 2331fd49ab..32136aa3a0 100644 --- a/SHAMap.h +++ b/SHAMap.h @@ -15,7 +15,7 @@ class SHAMap; // The trees are designed for rapid synchronization and compression of differences -class SHAMapNodeID +class SHAMapNode { // Identified a node in a SHA256 hash private: static uint256 smMasks[11]; // AND with hash to get node id @@ -29,32 +29,33 @@ public: static const int rootDepth=0; static const int leafDepth=10; - SHAMapNodeID(int depth, const uint256 &hash); + SHAMapNode(int depth, const uint256 &hash); int getDepth() { return mDepth; } const uint256 &getNodeID(); bool isRoot() const { return mDepth==0; } bool isLeaf() const { return mDepth==leafDepth; } bool isInner() const { return !isRoot() && !isLeaf(); } - SHAMapNodeID getParentNodeID() { return SHAMapNodeID(mDepth-1, mNodeID); } - SHAMapNodeID getChildNodeID(int m); + virtual bool IsPopulated(void) const { return false; } + SHAMapNode getParentNodeID() { return SHAMapNode(mDepth-1, mNodeID); } + SHAMapNode getChildNodeID(int m); int selectBranch(const uint256 &hash); static uint256 getNodeID(int depth, const uint256 &hash); - bool operator<(const SHAMapNodeID &) const; - bool operator>(const SHAMapNodeID &) const; - bool operator==(const SHAMapNodeID &) const; - bool operator!=(const SHAMapNodeID &) const; - bool operator<=(const SHAMapNodeID &) const; - bool operator>=(const SHAMapNodeID &) const; + bool operator<(const SHAMapNode &) const; + bool operator>(const SHAMapNode &) const; + bool operator==(const SHAMapNode &) const; + bool operator!=(const SHAMapNode &) const; + bool operator<=(const SHAMapNode &) const; + bool operator>=(const SHAMapNode &) const; - static void ClassInit(void); + static void ClassInit(); }; -class SHAMapLeafNode +class SHAMapLeafNode : public SHAMapNode { friend class SHAMap; @@ -62,26 +63,29 @@ public: typedef boost::shared_ptr pointer; private: - SHAMapNodeID mNodeID; uint256 mHash; std::list mHashes; - void updateHash(void); + void updateHash(); protected: - bool hasHash(const uint256 &hash) const; bool addHash(const uint256 &hash); bool delHash(const uint256 &hash); public: - SHAMapLeafNode(const uint256& NodeID); + SHAMapLeafNode(const SHAMapNode& nodeID); + + virtual bool IsPopulated(void) const { return true; } - const SHAMapNodeID& GetNodeID(void) const { return mNodeID; } const uint256& GetNodeHash() const { return mHash; } + bool isEmpty() const { return mHashes.empty(); } + int getHashCount() const { return mHashes.size(); } + const uint256& GetHash(int m) const; + bool hasHash(const uint256 &hash) const; }; -class SHAMapInnerNode +class SHAMapInnerNode : public SHAMapNode { friend class SHAMap; @@ -89,20 +93,22 @@ public: typedef boost::shared_ptr pointer; private: - SHAMapNodeID mNodeID; uint256 mHash; uint256 mHashes[32]; - void updateHash(void); + void updateHash(); protected: void SetChildHash(int m, const uint256 &hash); public: SHAMapInnerNode(int Depth, const uint256 &NodeID); - const SHAMapNodeID& GetNodeID() const { return mNodeID; } + + + virtual bool IsPopulated(void) const { return true; } const uint256& GetNodeHash() const { return mHash; } const uint256& GetChildHash(int m) const; + bool isEmpty() const; }; @@ -114,8 +120,9 @@ public: private: mutable boost::mutex mLock; - std::map mLeaves; - std::multimap mInnerNodes; + std::map mLeafByID; + std::map mInnerNodeByID; + std::map mNodeByHash; // includes nodes not present public: SHAMap(); @@ -123,18 +130,18 @@ public: ScopedLock Lock() const { return ScopedLock(mLock); } // inner node access functions - bool HasInnerNode(const SHAMapNodeID &id); + bool HasInnerNode(const SHAMapNode &id); bool GiveInnerNode(SHAMapInnerNode::pointer); - SHAMapInnerNode::pointer GetInnerNode(const SHAMapNodeID &); + SHAMapInnerNode::pointer GetInnerNode(const SHAMapNode &); // leaf node access functions - bool HasLeafNode(const SHAMapNodeID &id); + bool HasLeafNode(const SHAMapNode &id); bool GiveLeafNode(SHAMapLeafNode::pointer); - SHAMapLeafNode::pointer GetLeafNode(const SHAMapNodeID &); + SHAMapLeafNode::pointer GetLeafNode(const SHAMapNode &); // generic node functions - std::vector getRawNode(const SHAMapNodeID &id); - bool addRawNode(const SHAMapNodeID& nodeID, std::vector rawNode); + std::vector getRawNode(const SHAMapNode &id); + bool addRawNode(const SHAMapNode& nodeID, std::vector rawNode); // normal hash access functions bool hasHash(const uint256 &hash); @@ -145,9 +152,15 @@ public: bool nextHash(uint256 &hash); bool prevHash(uint256 &hash); - // special overloads for backed maps + // comparison/sync functions + void getMissingNodes(std::vector &nodeHashes, int max); + void getMissingObjects(std::vector &objectHashes, int max); + bool addKnownNode(const std::vector& rawNode); + + // overloads for backed maps virtual bool fetchNode(const uint256 &hash, std::vector& rawNode); virtual bool writeNode(const uint256 &hash, const std::vector& rawNode); + virtual bool haveObject(const uint256 &hash); }; #endif