Disallow automatic conversion between hash types

A templated BaseHash does not allow for automatic conversion, thus
conversions much be explicitly allowed / whitelisted, which will
reduce the risk of unintended conversions.
This commit is contained in:
Ben Woosley
2020-01-15 14:03:57 -08:00
parent fa9ef2cdbe
commit 4d7369125a
2 changed files with 85 additions and 23 deletions

View File

@@ -16,17 +16,17 @@ typedef std::vector<unsigned char> valtype;
bool fAcceptDatacarrier = DEFAULT_ACCEPT_DATACARRIER; bool fAcceptDatacarrier = DEFAULT_ACCEPT_DATACARRIER;
unsigned nMaxDatacarrierBytes = MAX_OP_RETURN_RELAY; unsigned nMaxDatacarrierBytes = MAX_OP_RETURN_RELAY;
CScriptID::CScriptID(const CScript& in) : uint160(Hash160(in.begin(), in.end())) {} CScriptID::CScriptID(const CScript& in) : BaseHash(Hash160(in.begin(), in.end())) {}
CScriptID::CScriptID(const ScriptHash& in) : uint160(static_cast<uint160>(in)) {} CScriptID::CScriptID(const ScriptHash& in) : BaseHash(static_cast<uint160>(in)) {}
ScriptHash::ScriptHash(const CScript& in) : uint160(Hash160(in.begin(), in.end())) {} ScriptHash::ScriptHash(const CScript& in) : BaseHash(Hash160(in.begin(), in.end())) {}
ScriptHash::ScriptHash(const CScriptID& in) : uint160(static_cast<uint160>(in)) {} ScriptHash::ScriptHash(const CScriptID& in) : BaseHash(static_cast<uint160>(in)) {}
PKHash::PKHash(const CPubKey& pubkey) : uint160(pubkey.GetID()) {} PKHash::PKHash(const CPubKey& pubkey) : BaseHash(pubkey.GetID()) {}
PKHash::PKHash(const CKeyID& pubkey_id) : uint160(pubkey_id) {} PKHash::PKHash(const CKeyID& pubkey_id) : BaseHash(pubkey_id) {}
WitnessV0KeyHash::WitnessV0KeyHash(const CPubKey& pubkey) : uint160(pubkey.GetID()) {} WitnessV0KeyHash::WitnessV0KeyHash(const CPubKey& pubkey) : BaseHash(pubkey.GetID()) {}
WitnessV0KeyHash::WitnessV0KeyHash(const PKHash& pubkey_hash) : uint160(static_cast<uint160>(pubkey_hash)) {} WitnessV0KeyHash::WitnessV0KeyHash(const PKHash& pubkey_hash) : BaseHash(static_cast<uint160>(pubkey_hash)) {}
CKeyID ToKeyID(const PKHash& key_hash) CKeyID ToKeyID(const PKHash& key_hash)
{ {

View File

@@ -20,13 +20,74 @@ class CKeyID;
class CScript; class CScript;
struct ScriptHash; struct ScriptHash;
template<typename HashType>
class BaseHash
{
protected:
HashType m_hash;
public:
BaseHash() : m_hash() {}
BaseHash(const HashType& in) : m_hash(in) {}
unsigned char* begin()
{
return m_hash.begin();
}
const unsigned char* begin() const
{
return m_hash.begin();
}
unsigned char* end()
{
return m_hash.end();
}
const unsigned char* end() const
{
return m_hash.end();
}
operator std::vector<unsigned char>() const
{
return std::vector<unsigned char>{m_hash.begin(), m_hash.end()};
}
std::string ToString() const
{
return m_hash.ToString();
}
bool operator==(const BaseHash<HashType>& other) const noexcept
{
return m_hash == other.m_hash;
}
bool operator!=(const BaseHash<HashType>& other) const noexcept
{
return !(m_hash == other.m_hash);
}
bool operator<(const BaseHash<HashType>& other) const noexcept
{
return m_hash < other.m_hash;
}
size_t size() const
{
return m_hash.size();
}
};
/** A reference to a CScript: the Hash160 of its serialization (see script.h) */ /** A reference to a CScript: the Hash160 of its serialization (see script.h) */
class CScriptID : public uint160 class CScriptID : public BaseHash<uint160>
{ {
public: public:
CScriptID() : uint160() {} CScriptID() : BaseHash() {}
explicit CScriptID(const CScript& in); explicit CScriptID(const CScript& in);
explicit CScriptID(const uint160& in) : uint160(in) {} explicit CScriptID(const uint160& in) : BaseHash(in) {}
explicit CScriptID(const ScriptHash& in); explicit CScriptID(const ScriptHash& in);
}; };
@@ -75,39 +136,40 @@ public:
friend bool operator<(const CNoDestination &a, const CNoDestination &b) { return true; } friend bool operator<(const CNoDestination &a, const CNoDestination &b) { return true; }
}; };
struct PKHash : public uint160 struct PKHash : public BaseHash<uint160>
{ {
PKHash() : uint160() {} PKHash() : BaseHash() {}
explicit PKHash(const uint160& hash) : uint160(hash) {} explicit PKHash(const uint160& hash) : BaseHash(hash) {}
explicit PKHash(const CPubKey& pubkey); explicit PKHash(const CPubKey& pubkey);
explicit PKHash(const CKeyID& pubkey_id); explicit PKHash(const CKeyID& pubkey_id);
}; };
CKeyID ToKeyID(const PKHash& key_hash); CKeyID ToKeyID(const PKHash& key_hash);
struct WitnessV0KeyHash; struct WitnessV0KeyHash;
struct ScriptHash : public uint160 struct ScriptHash : public BaseHash<uint160>
{ {
ScriptHash() : uint160() {} ScriptHash() : BaseHash() {}
// These don't do what you'd expect. // These don't do what you'd expect.
// Use ScriptHash(GetScriptForDestination(...)) instead. // Use ScriptHash(GetScriptForDestination(...)) instead.
explicit ScriptHash(const WitnessV0KeyHash& hash) = delete; explicit ScriptHash(const WitnessV0KeyHash& hash) = delete;
explicit ScriptHash(const PKHash& hash) = delete; explicit ScriptHash(const PKHash& hash) = delete;
explicit ScriptHash(const uint160& hash) : uint160(hash) {}
explicit ScriptHash(const uint160& hash) : BaseHash(hash) {}
explicit ScriptHash(const CScript& script); explicit ScriptHash(const CScript& script);
explicit ScriptHash(const CScriptID& script); explicit ScriptHash(const CScriptID& script);
}; };
struct WitnessV0ScriptHash : public uint256 struct WitnessV0ScriptHash : public BaseHash<uint256>
{ {
WitnessV0ScriptHash() : uint256() {} WitnessV0ScriptHash() : BaseHash() {}
explicit WitnessV0ScriptHash(const uint256& hash) : uint256(hash) {} explicit WitnessV0ScriptHash(const uint256& hash) : BaseHash(hash) {}
explicit WitnessV0ScriptHash(const CScript& script); explicit WitnessV0ScriptHash(const CScript& script);
}; };
struct WitnessV0KeyHash : public uint160 struct WitnessV0KeyHash : public BaseHash<uint160>
{ {
WitnessV0KeyHash() : uint160() {} WitnessV0KeyHash() : BaseHash() {}
explicit WitnessV0KeyHash(const uint160& hash) : uint160(hash) {} explicit WitnessV0KeyHash(const uint160& hash) : BaseHash(hash) {}
explicit WitnessV0KeyHash(const CPubKey& pubkey); explicit WitnessV0KeyHash(const CPubKey& pubkey);
explicit WitnessV0KeyHash(const PKHash& pubkey_hash); explicit WitnessV0KeyHash(const PKHash& pubkey_hash);
}; };