partial bitcoin#17938: Disallow automatic conversion between disparate hash types

includes:
- 0a5ea32ce605984094c5552877cb99bc81654f2c
- 3fcc46812334074d2c77a6233e8a961cd0785872
- 2c54217f913967703b404747133be67cf2f4feac
- 966a22d859db37b1775e2180e5be032fc4fdf483
- 4d7369125a82214ea42b808a32b71b315a5c3c72
This commit is contained in:
Kittywhiskers Van Gogh 2023-04-05 21:48:02 +00:00 committed by PastaPastaPasta
parent 8d5ae627b8
commit 00802bb21d
11 changed files with 102 additions and 30 deletions

View File

@ -1416,7 +1416,7 @@ template <typename ProTx>
static bool CheckHashSig(const ProTx& proTx, const PKHash& pkhash, CValidationState& state) static bool CheckHashSig(const ProTx& proTx, const PKHash& pkhash, CValidationState& state)
{ {
std::string strError; std::string strError;
if (!CHashSigner::VerifyHash(::SerializeHash(proTx), CKeyID(pkhash), proTx.vchSig, strError)) { if (!CHashSigner::VerifyHash(::SerializeHash(proTx), ToKeyID(pkhash), proTx.vchSig, strError)) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-protx-sig"); return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-protx-sig");
} }
return true; return true;
@ -1426,7 +1426,7 @@ template <typename ProTx>
static bool CheckStringSig(const ProTx& proTx, const PKHash& pkhash, CValidationState& state) static bool CheckStringSig(const ProTx& proTx, const PKHash& pkhash, CValidationState& state)
{ {
std::string strError; std::string strError;
if (!CMessageSigner::VerifyMessage(CKeyID(pkhash), proTx.vchSig, proTx.MakeSignString(), strError)) { if (!CMessageSigner::VerifyMessage(ToKeyID(pkhash), proTx.vchSig, proTx.MakeSignString(), strError)) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-protx-sig"); return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-protx-sig");
} }
return true; return true;

View File

@ -512,7 +512,7 @@ void CoinControlDialog::updateLabels(CCoinControl& m_coin_control, WalletModel *
{ {
CPubKey pubkey; CPubKey pubkey;
PKHash *pkhash = std::get_if<PKHash>(&address); PKHash *pkhash = std::get_if<PKHash>(&address);
if (pkhash && model->wallet().getPubKey(out.txout.scriptPubKey, CKeyID(*pkhash), pubkey)) if (pkhash && model->wallet().getPubKey(out.txout.scriptPubKey, ToKeyID(*pkhash), pubkey))
{ {
nBytesInputs += (pubkey.IsCompressed() ? 148 : 180); nBytesInputs += (pubkey.IsCompressed() ? 148 : 180);
} }

View File

@ -178,7 +178,7 @@ static CKeyID ParsePubKeyIDFromAddress(const std::string& strAddress, const std:
if (!pkhash) { if (!pkhash) {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("%s must be a valid P2PKH address, not %s", paramName, strAddress)); throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("%s must be a valid P2PKH address, not %s", paramName, strAddress));
} }
return CKeyID(*pkhash); return ToKeyID(*pkhash);
} }
static CBLSPublicKey ParseBLSPubKey(const std::string& hexKey, const std::string& paramName, bool specific_legacy_bls_scheme = false) static CBLSPublicKey ParseBLSPubKey(const std::string& hexKey, const std::string& paramName, bool specific_legacy_bls_scheme = false)
@ -773,7 +773,7 @@ static UniValue protx_register_common_wrapper(const JSONRPCRequest& request,
} }
CKey key; CKey key;
if (!spk_man->GetKey(CKeyID(*pkhash), key)) { if (!spk_man->GetKey(ToKeyID(*pkhash), key)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("collateral key not in wallet: %s", EncodeDestination(txDest))); throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("collateral key not in wallet: %s", EncodeDestination(txDest)));
} }
SignSpecialTxPayloadByString(tx, ptx, key); SignSpecialTxPayloadByString(tx, ptx, key);
@ -1235,7 +1235,7 @@ static bool CheckWalletOwnsScript(CWallet* pwallet, const CScript& script) {
CTxDestination dest; CTxDestination dest;
if (ExtractDestination(script, dest)) { if (ExtractDestination(script, dest)) {
if ((std::get_if<PKHash>(&dest) && spk_man->HaveKey(CKeyID(*std::get_if<PKHash>(&dest)))) || (std::get_if<ScriptHash>(&dest) && spk_man->HaveCScript(ScriptHash(*std::get_if<ScriptHash>(&dest))))) { if ((std::get_if<PKHash>(&dest) && spk_man->HaveKey(ToKeyID(*std::get_if<PKHash>(&dest)))) || (std::get_if<ScriptHash>(&dest) && spk_man->HaveCScript(CScriptID{ScriptHash(*std::get_if<ScriptHash>(&dest))}))) {
return true; return true;
} }
} }

View File

@ -197,7 +197,7 @@ CPubKey AddrToPubKey(const FillableSigningProvider& keystore, const std::string&
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("%s does not refer to a key", addr_in)); throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("%s does not refer to a key", addr_in));
} }
CPubKey vchPubKey; CPubKey vchPubKey;
if (!keystore.GetPubKey(CKeyID(*pkhash), vchPubKey)) { if (!keystore.GetPubKey(ToKeyID(*pkhash), vchPubKey)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("no full public key for address %s", addr_in)); throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("no full public key for address %s", addr_in));
} }
if (!vchPubKey.IsFullyValid()) { if (!vchPubKey.IsFullyValid()) {

View File

@ -123,7 +123,7 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
} }
case TxoutType::SCRIPTHASH: case TxoutType::SCRIPTHASH:
h160 = uint160(vSolutions[0]); h160 = uint160(vSolutions[0]);
if (GetCScript(provider, sigdata, h160, scriptRet)) { if (GetCScript(provider, sigdata, CScriptID{h160}, scriptRet)) {
ret.push_back(std::vector<unsigned char>(scriptRet.begin(), scriptRet.end())); ret.push_back(std::vector<unsigned char>(scriptRet.begin(), scriptRet.end()));
return true; return true;
} }

View File

@ -13,11 +13,19 @@ 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) : 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) : 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) : BaseHash(pubkey_id) {}
CKeyID ToKeyID(const PKHash& key_hash)
{
return CKeyID{static_cast<uint160>(key_hash)};
}
const char* GetTxnOutputType(TxoutType t) const char* GetTxnOutputType(TxoutType t)
{ {

View File

@ -15,14 +15,77 @@ static const bool DEFAULT_ACCEPT_DATACARRIER = true;
class CKeyID; class CKeyID;
class CScript; class CScript;
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);
CScriptID(const uint160& in) : uint160(in) {} explicit CScriptID(const uint160& in) : BaseHash(in) {}
explicit CScriptID(const ScriptHash& in);
}; };
/** /**
@ -67,20 +130,21 @@ 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);
using uint160::uint160; explicit PKHash(const CKeyID& pubkey_id);
}; };
CKeyID ToKeyID(const PKHash& key_hash);
struct ScriptHash : public uint160 struct ScriptHash : public BaseHash<uint160>
{ {
ScriptHash() : uint160() {} ScriptHash() : BaseHash() {}
explicit ScriptHash(const uint160& hash) : uint160(hash) {} explicit ScriptHash(const uint160& hash) : BaseHash(hash) {}
explicit ScriptHash(const CScript& script); explicit ScriptHash(const CScript& script);
using uint160::uint160; explicit ScriptHash(const CScriptID& script);
}; };
/** /**

View File

@ -286,7 +286,7 @@ bool CSporkManager::SetSporkAddress(const std::string& strAddress)
LogPrintf("CSporkManager::SetSporkAddress -- Failed to parse spork address\n"); LogPrintf("CSporkManager::SetSporkAddress -- Failed to parse spork address\n");
return false; return false;
} }
setSporkPubKeyIDs.insert(CKeyID(*pkhash)); setSporkPubKeyIDs.insert(ToKeyID(*pkhash));
return true; return true;
} }

View File

@ -145,7 +145,7 @@ UniValue importprivkey(const JSONRPCRequest& request)
} }
// Use timestamp of 1 to scan the whole chain // Use timestamp of 1 to scan the whole chain
if (!pwallet->ImportPrivKeys({{CKeyID(vchAddress), key}}, 1)) { if (!pwallet->ImportPrivKeys({{ToKeyID(vchAddress), key}}, 1)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet"); throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet");
} }
} }
@ -829,7 +829,7 @@ UniValue dumpprivkey(const JSONRPCRequest& request)
throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to a key"); throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to a key");
} }
CKey vchSecret; CKey vchSecret;
if (!spk_man.GetKey(CKeyID(*pkhash), vchSecret)) { if (!spk_man.GetKey(ToKeyID(*pkhash), vchSecret)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Private key for address " + strAddress + " is not known"); throw JSONRPCError(RPC_WALLET_ERROR, "Private key for address " + strAddress + " is not known");
} }
return EncodeSecret(vchSecret); return EncodeSecret(vchSecret);

View File

@ -3564,7 +3564,7 @@ public:
UniValue operator()(const CNoDestination &dest) const { return UniValue(UniValue::VOBJ); } UniValue operator()(const CNoDestination &dest) const { return UniValue(UniValue::VOBJ); }
UniValue operator()(const PKHash& pkhash) const { UniValue operator()(const PKHash& pkhash) const {
CKeyID keyID(pkhash); CKeyID keyID{ToKeyID(pkhash)};
UniValue obj(UniValue::VOBJ); UniValue obj(UniValue::VOBJ);
CPubKey vchPubKey; CPubKey vchPubKey;
if (provider && provider->GetPubKey(keyID, vchPubKey)) { if (provider && provider->GetPubKey(keyID, vchPubKey)) {
@ -3727,7 +3727,7 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
CHDChain hdChainCurrent; CHDChain hdChainCurrent;
LegacyScriptPubKeyMan* legacy_spk_man = pwallet->GetLegacyScriptPubKeyMan(); LegacyScriptPubKeyMan* legacy_spk_man = pwallet->GetLegacyScriptPubKeyMan();
if (legacy_spk_man != nullptr) { if (legacy_spk_man != nullptr) {
if (pkhash && legacy_spk_man->HaveHDKey(CKeyID(*pkhash), hdChainCurrent)) { if (pkhash && legacy_spk_man->HaveHDKey(ToKeyID(*pkhash), hdChainCurrent)) {
ret.pushKV("hdchainid", hdChainCurrent.GetID().GetHex()); ret.pushKV("hdchainid", hdChainCurrent.GetID().GetHex());
} }
} }

View File

@ -685,7 +685,7 @@ bool LegacyScriptPubKeyMan::SignTransaction(CMutableTransaction& tx, const std::
SigningResult LegacyScriptPubKeyMan::SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const SigningResult LegacyScriptPubKeyMan::SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const
{ {
CKeyID key_id(pkhash); CKeyID key_id(ToKeyID(pkhash));
CKey key; CKey key;
if (!GetKey(key_id, key)) { if (!GetKey(key_id, key)) {
return SigningResult::PRIVATE_KEY_NOT_AVAILABLE; return SigningResult::PRIVATE_KEY_NOT_AVAILABLE;
@ -744,8 +744,8 @@ const CKeyMetadata* LegacyScriptPubKeyMan::GetMetadata(const CTxDestination& des
LOCK(cs_KeyStore); LOCK(cs_KeyStore);
const PKHash *pkhash = std::get_if<PKHash>(&dest); const PKHash *pkhash = std::get_if<PKHash>(&dest);
if (pkhash != nullptr && !pkhash->IsNull()) { if (pkhash != nullptr && !ToKeyID(*pkhash).IsNull()) {
auto it = mapKeyMetadata.find(CKeyID(*pkhash)); auto it = mapKeyMetadata.find(ToKeyID(*pkhash));
if (it != mapKeyMetadata.end()) { if (it != mapKeyMetadata.end()) {
return &it->second; return &it->second;
} }