const& _h)
{
return (*this |= _h.template bloomPart());
}
template inline bool containsBloom(FixedHash const& _h)
{
return contains(_h.template bloomPart());
}
template inline FixedHash bloomPart() const
{
unsigned const c_bloomBits = M * 8;
unsigned const c_mask = c_bloomBits - 1;
unsigned const c_bloomBytes = (StaticLog2::result + 7) / 8;
static_assert((M & (M - 1)) == 0, "M must be power-of-two");
static_assert(P * c_bloomBytes <= N, "out of range");
FixedHash ret;
byte const* p = data();
for (unsigned i = 0; i < P; ++i)
{
unsigned index = 0;
for (unsigned j = 0; j < c_bloomBytes; ++j, ++p)
index = (index << 8) | *p;
index &= c_mask;
ret[M - 1 - index / 8] |= (1 << (index % 8));
}
return ret;
}
/// Returns the index of the first bit set to one, or size() * 8 if no bits are set.
inline unsigned firstBitSet() const
{
unsigned ret = 0;
for (auto d: m_data)
if (d)
for (;; ++ret, d <<= 1)
if (d & 0x80)
return ret;
else {}
else
ret += 8;
return ret;
}
void clear() { m_data.fill(0); }
private:
std::array m_data; ///< The binary data.
};
template
class SecureFixedHash: private FixedHash
{
public:
using ConstructFromHashType = typename FixedHash::ConstructFromHashType;
using ConstructFromStringType = typename FixedHash::ConstructFromStringType;
using ConstructFromPointerType = typename FixedHash::ConstructFromPointerType;
SecureFixedHash() = default;
explicit SecureFixedHash(bytes const& _b, ConstructFromHashType _t = FixedHash::FailIfDifferent): FixedHash(_b, _t) {}
explicit SecureFixedHash(bytesConstRef _b, ConstructFromHashType _t = FixedHash::FailIfDifferent): FixedHash(_b, _t) {}
explicit SecureFixedHash(bytesSec const& _b, ConstructFromHashType _t = FixedHash::FailIfDifferent): FixedHash(_b.ref(), _t) {}
template explicit SecureFixedHash(FixedHash const& _h, ConstructFromHashType _t = FixedHash::AlignLeft): FixedHash(_h, _t) {}
template explicit SecureFixedHash(SecureFixedHash const& _h, ConstructFromHashType _t = FixedHash::AlignLeft): FixedHash(_h.makeInsecure(), _t) {}
explicit SecureFixedHash(std::string const& _s, ConstructFromStringType _t = FixedHash::FromHex, ConstructFromHashType _ht = FixedHash::FailIfDifferent): FixedHash(_s, _t, _ht) {}
explicit SecureFixedHash(bytes const* _d, ConstructFromPointerType _t): FixedHash(_d, _t) {}
~SecureFixedHash() { ref().cleanse(); }
SecureFixedHash& operator=(SecureFixedHash const& _c)
{
if (&_c == this)
return *this;
ref().cleanse();
FixedHash::operator=(static_cast const&>(_c));
return *this;
}
using FixedHash::size;
bytesSec asBytesSec() const { return bytesSec(ref()); }
FixedHash const& makeInsecure() const { return static_cast const&>(*this); }
FixedHash& writable() { clear(); return static_cast&>(*this); }
using FixedHash::operator bool;
// The obvious comparison operators.
bool operator==(SecureFixedHash const& _c) const { return static_cast const&>(*this).operator==(static_cast const&>(_c)); }
bool operator!=(SecureFixedHash const& _c) const { return static_cast const&>(*this).operator!=(static_cast const&>(_c)); }
bool operator<(SecureFixedHash const& _c) const { return static_cast const&>(*this).operator<(static_cast const&>(_c)); }
bool operator>=(SecureFixedHash const& _c) const { return static_cast const&>(*this).operator>=(static_cast const&>(_c)); }
bool operator<=(SecureFixedHash const& _c) const { return static_cast const&>(*this).operator<=(static_cast const&>(_c)); }
bool operator>(SecureFixedHash const& _c) const { return static_cast const&>(*this).operator>(static_cast const&>(_c)); }
using FixedHash::operator==;
using FixedHash::operator!=;
using FixedHash::operator<;
using FixedHash::operator>=;
using FixedHash::operator<=;
using FixedHash::operator>;
// The obvious binary operators.
SecureFixedHash& operator^=(FixedHash const& _c) { static_cast&>(*this).operator^=(_c); return *this; }
SecureFixedHash operator^(FixedHash const& _c) const { return SecureFixedHash(*this) ^= _c; }
SecureFixedHash& operator|=(FixedHash const& _c) { static_cast&>(*this).operator^=(_c); return *this; }
SecureFixedHash operator|(FixedHash const& _c) const { return SecureFixedHash(*this) |= _c; }
SecureFixedHash& operator&=(FixedHash const& _c) { static_cast&>(*this).operator^=(_c); return *this; }
SecureFixedHash operator&(FixedHash const& _c) const { return SecureFixedHash(*this) &= _c; }
SecureFixedHash& operator^=(SecureFixedHash const& _c) { static_cast&>(*this).operator^=(static_cast const&>(_c)); return *this; }
SecureFixedHash operator^(SecureFixedHash const& _c) const { return SecureFixedHash(*this) ^= _c; }
SecureFixedHash& operator|=(SecureFixedHash const& _c) { static_cast&>(*this).operator^=(static_cast const&>(_c)); return *this; }
SecureFixedHash operator|(SecureFixedHash const& _c) const { return SecureFixedHash(*this) |= _c; }
SecureFixedHash& operator&=(SecureFixedHash const& _c) { static_cast&>(*this).operator^=(static_cast const&>(_c)); return *this; }
SecureFixedHash operator&(SecureFixedHash const& _c) const { return SecureFixedHash(*this) &= _c; }
SecureFixedHash operator~() const { auto r = ~static_cast const&>(*this); return static_cast(r); }
using FixedHash::abridged;
using FixedHash::abridgedMiddle;
bytesConstRef ref() const { return FixedHash::ref(); }
byte const* data() const { return FixedHash::data(); }
static SecureFixedHash random() { SecureFixedHash ret; ret.randomize(s_fixedHashEngine); return ret; }
using FixedHash::firstBitSet;
void clear() { ref().cleanse(); }
};
/// Fast equality operator for h256.
template<> inline bool FixedHash<32>::operator==(FixedHash<32> const& _other) const
{
const uint64_t* hash1 = (const uint64_t*)data();
const uint64_t* hash2 = (const uint64_t*)_other.data();
return (hash1[0] == hash2[0]) && (hash1[1] == hash2[1]) && (hash1[2] == hash2[2]) && (hash1[3] == hash2[3]);
}
/// Fast std::hash compatible hash function object for h256.
template<> inline size_t FixedHash<32>::hash::operator()(FixedHash<32> const& value) const
{
uint64_t const* data = reinterpret_cast(value.data());
return boost::hash_range(data, data + 4);
}
/// Stream I/O for the FixedHash class.
template
inline std::ostream& operator<<(std::ostream& _out, FixedHash const& _h)
{
_out << std::noshowbase << std::hex << std::setfill('0');
for (unsigned i = 0; i < N; ++i)
_out << std::setw(2) << (int)_h[i];
_out << std::dec;
return _out;
}
/// Stream I/O for the SecureFixedHash class.
template
inline std::ostream& operator<<(std::ostream& _out, SecureFixedHash const& _h)
{
_out << "SecureFixedHash#" << std::hex << typename FixedHash::hash()(_h.makeInsecure()) << std::dec;
return _out;
}
// Common types of FixedHash.
using h2048 = FixedHash<256>;
using h1024 = FixedHash<128>;
using h520 = FixedHash<65>;
using h512 = FixedHash<64>;
using h256 = FixedHash<32>;
using h160 = FixedHash<20>;
using h128 = FixedHash<16>;
using h64 = FixedHash<8>;
using h512s = std::vector;
using h256s = std::vector;
using h160s = std::vector;
using h256Set = std::set;
using h160Set = std::set;
using h256Hash = std::unordered_set;
using h160Hash = std::unordered_set;
/// Convert the given value into h160 (160-bit unsigned integer) using the right 20 bytes.
inline h160 right160(h256 const& _t)
{
h160 ret;
memcpy(ret.data(), _t.data() + 12, 20);
return ret;
}
/// Convert the given value into h160 (160-bit unsigned integer) using the left 20 bytes.
inline h160 left160(h256 const& _t)
{
h160 ret;
memcpy(&ret[0], _t.data(), 20);
return ret;
}
h128 fromUUID(std::string const& _uuid);
std::string toUUID(h128 const& _uuid);
inline std::string toString(h256s const& _bs)
{
std::ostringstream out;
out << "[ ";
for (auto i: _bs)
out << i.abridged() << ", ";
out << "]";
return out.str();
}
}
namespace std
{
/// Forward std::hash to dev::FixedHash::hash.
template<> struct hash: dev::h64::hash {};
template<> struct hash: dev::h128::hash {};
template<> struct hash: dev::h160::hash {};
template<> struct hash: dev::h256::hash {};
template<> struct hash: dev::h512::hash {};
}