//------------------------------------------------------------------------------ /* Copyright (c) 2011-2013, OpenCoin, Inc. */ //============================================================================== SETUP_LOG (SHAMapNode) // canonicalize the hash to a node ID for this depth SHAMapNode::SHAMapNode (int depth, uint256 const& hash) : mNodeID (hash), mDepth (depth), mHash (0) { assert ((depth >= 0) && (depth < 65)); mNodeID &= smMasks[depth]; } SHAMapNode::SHAMapNode (const void* ptr, int len) : mHash (0) { if (len < 33) mDepth = -1; else { memcpy (mNodeID.begin (), ptr, 32); mDepth = * (static_cast (ptr) + 32); } } std::string SHAMapNode::getString () const { static boost::format NodeID ("NodeID(%s,%s)"); if ((mDepth == 0) && (mNodeID.isZero ())) return "NodeID(root)"; return str (boost::format (NodeID) % boost::lexical_cast (mDepth) % mNodeID.GetHex ()); } uint256 SHAMapNode::smMasks[65]; // VFALCO TODO use a static initializer to do this instead bool SMN_j = SHAMapNode::ClassInit (); // set up the depth masks bool SHAMapNode::ClassInit () { uint256 selector; for (int i = 0; i < 64; i += 2) { // VFALCO TODO group these statics together in an object smMasks[i] = selector; * (selector.begin () + (i / 2)) = 0xF0; smMasks[i + 1] = selector; * (selector.begin () + (i / 2)) = 0xFF; } smMasks[64] = selector; return true; } bool SHAMapNode::operator< (const SHAMapNode& s) const { if (s.mDepth < mDepth) return true; if (s.mDepth > mDepth) return false; return mNodeID < s.mNodeID; } bool SHAMapNode::operator> (const SHAMapNode& s) const { if (s.mDepth < mDepth) return false; if (s.mDepth > mDepth) return true; return mNodeID > s.mNodeID; } bool SHAMapNode::operator<= (const SHAMapNode& s) const { if (s.mDepth < mDepth) return true; if (s.mDepth > mDepth) return false; return mNodeID <= s.mNodeID; } bool SHAMapNode::operator>= (const SHAMapNode& s) const { if (s.mDepth < mDepth) return false; if (s.mDepth > mDepth) return true; return mNodeID >= s.mNodeID; } uint256 SHAMapNode::getNodeID (int depth, uint256 const& hash) { assert ((depth >= 0) && (depth <= 64)); return hash & smMasks[depth]; } void SHAMapNode::addIDRaw (Serializer& s) const { s.add256 (mNodeID); s.add8 (mDepth); } std::string SHAMapNode::getRawString () const { Serializer s (33); addIDRaw (s); return s.getString (); } // This can be optimized to avoid the << if needed SHAMapNode SHAMapNode::getChildNodeID (int m) const { assert ((m >= 0) && (m < 16)); uint256 child (mNodeID); child.begin ()[mDepth / 2] |= (mDepth & 1) ? m : (m << 4); return SHAMapNode (mDepth + 1, child, true); } // Which branch would contain the specified hash int SHAMapNode::selectBranch (uint256 const& hash) const { #ifdef PARANOID if (mDepth >= 64) { assert (false); return -1; } if ((hash & smMasks[mDepth]) != mNodeID) { std::cerr << "selectBranch(" << getString () << std::endl; std::cerr << " " << hash << " off branch" << std::endl; assert (false); return -1; // does not go under this node } #endif int branch = * (hash.begin () + (mDepth / 2)); if (mDepth & 1) branch &= 0xf; else branch >>= 4; assert ((branch >= 0) && (branch < 16)); return branch; } void SHAMapNode::dump () const { WriteLog (lsDEBUG, SHAMapNode) << getString (); }