From 4d7369125a82214ea42b808a32b71b315a5c3c72 Mon Sep 17 00:00:00 2001 From: Ben Woosley Date: Wed, 15 Jan 2020 14:03:57 -0800 Subject: 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. --- src/script/standard.h | 92 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 77 insertions(+), 15 deletions(-) (limited to 'src/script/standard.h') diff --git a/src/script/standard.h b/src/script/standard.h index d235e6e173..4baed6da6e 100644 --- a/src/script/standard.h +++ b/src/script/standard.h @@ -20,13 +20,74 @@ class CKeyID; class CScript; struct ScriptHash; +template +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() const + { + return std::vector{m_hash.begin(), m_hash.end()}; + } + + std::string ToString() const + { + return m_hash.ToString(); + } + + bool operator==(const BaseHash& other) const noexcept + { + return m_hash == other.m_hash; + } + + bool operator!=(const BaseHash& other) const noexcept + { + return !(m_hash == other.m_hash); + } + + bool operator<(const BaseHash& 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) */ -class CScriptID : public uint160 +class CScriptID : public BaseHash { public: - CScriptID() : uint160() {} + CScriptID() : BaseHash() {} explicit CScriptID(const CScript& in); - explicit CScriptID(const uint160& in) : uint160(in) {} + explicit CScriptID(const uint160& in) : BaseHash(in) {} explicit CScriptID(const ScriptHash& in); }; @@ -75,39 +136,40 @@ public: friend bool operator<(const CNoDestination &a, const CNoDestination &b) { return true; } }; -struct PKHash : public uint160 +struct PKHash : public BaseHash { - PKHash() : uint160() {} - explicit PKHash(const uint160& hash) : uint160(hash) {} + PKHash() : BaseHash() {} + explicit PKHash(const uint160& hash) : BaseHash(hash) {} explicit PKHash(const CPubKey& pubkey); explicit PKHash(const CKeyID& pubkey_id); }; CKeyID ToKeyID(const PKHash& key_hash); struct WitnessV0KeyHash; -struct ScriptHash : public uint160 +struct ScriptHash : public BaseHash { - ScriptHash() : uint160() {} + ScriptHash() : BaseHash() {} // These don't do what you'd expect. // Use ScriptHash(GetScriptForDestination(...)) instead. explicit ScriptHash(const WitnessV0KeyHash& 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 CScriptID& script); }; -struct WitnessV0ScriptHash : public uint256 +struct WitnessV0ScriptHash : public BaseHash { - WitnessV0ScriptHash() : uint256() {} - explicit WitnessV0ScriptHash(const uint256& hash) : uint256(hash) {} + WitnessV0ScriptHash() : BaseHash() {} + explicit WitnessV0ScriptHash(const uint256& hash) : BaseHash(hash) {} explicit WitnessV0ScriptHash(const CScript& script); }; -struct WitnessV0KeyHash : public uint160 +struct WitnessV0KeyHash : public BaseHash { - WitnessV0KeyHash() : uint160() {} - explicit WitnessV0KeyHash(const uint160& hash) : uint160(hash) {} + WitnessV0KeyHash() : BaseHash() {} + explicit WitnessV0KeyHash(const uint160& hash) : BaseHash(hash) {} explicit WitnessV0KeyHash(const CPubKey& pubkey); explicit WitnessV0KeyHash(const PKHash& pubkey_hash); }; -- cgit v1.2.3