Skip to content

Commit 00802bb

Browse files
kwvgPastaPastaPasta
authored andcommitted
partial bitcoin#17938: Disallow automatic conversion between disparate hash types
includes: - 0a5ea32 - 3fcc468 - 2c54217 - 966a22d - 4d73691
1 parent 8d5ae62 commit 00802bb

File tree

11 files changed

+102
-30
lines changed

11 files changed

+102
-30
lines changed

src/evo/deterministicmns.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1416,7 +1416,7 @@ template <typename ProTx>
14161416
static bool CheckHashSig(const ProTx& proTx, const PKHash& pkhash, CValidationState& state)
14171417
{
14181418
std::string strError;
1419-
if (!CHashSigner::VerifyHash(::SerializeHash(proTx), CKeyID(pkhash), proTx.vchSig, strError)) {
1419+
if (!CHashSigner::VerifyHash(::SerializeHash(proTx), ToKeyID(pkhash), proTx.vchSig, strError)) {
14201420
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-protx-sig");
14211421
}
14221422
return true;
@@ -1426,7 +1426,7 @@ template <typename ProTx>
14261426
static bool CheckStringSig(const ProTx& proTx, const PKHash& pkhash, CValidationState& state)
14271427
{
14281428
std::string strError;
1429-
if (!CMessageSigner::VerifyMessage(CKeyID(pkhash), proTx.vchSig, proTx.MakeSignString(), strError)) {
1429+
if (!CMessageSigner::VerifyMessage(ToKeyID(pkhash), proTx.vchSig, proTx.MakeSignString(), strError)) {
14301430
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-protx-sig");
14311431
}
14321432
return true;

src/qt/coincontroldialog.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,7 @@ void CoinControlDialog::updateLabels(CCoinControl& m_coin_control, WalletModel *
512512
{
513513
CPubKey pubkey;
514514
PKHash *pkhash = std::get_if<PKHash>(&address);
515-
if (pkhash && model->wallet().getPubKey(out.txout.scriptPubKey, CKeyID(*pkhash), pubkey))
515+
if (pkhash && model->wallet().getPubKey(out.txout.scriptPubKey, ToKeyID(*pkhash), pubkey))
516516
{
517517
nBytesInputs += (pubkey.IsCompressed() ? 148 : 180);
518518
}

src/rpc/evo.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ static CKeyID ParsePubKeyIDFromAddress(const std::string& strAddress, const std:
178178
if (!pkhash) {
179179
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("%s must be a valid P2PKH address, not %s", paramName, strAddress));
180180
}
181-
return CKeyID(*pkhash);
181+
return ToKeyID(*pkhash);
182182
}
183183

184184
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,
773773
}
774774

775775
CKey key;
776-
if (!spk_man->GetKey(CKeyID(*pkhash), key)) {
776+
if (!spk_man->GetKey(ToKeyID(*pkhash), key)) {
777777
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("collateral key not in wallet: %s", EncodeDestination(txDest)));
778778
}
779779
SignSpecialTxPayloadByString(tx, ptx, key);
@@ -1235,7 +1235,7 @@ static bool CheckWalletOwnsScript(CWallet* pwallet, const CScript& script) {
12351235

12361236
CTxDestination dest;
12371237
if (ExtractDestination(script, dest)) {
1238-
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))))) {
1238+
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))}))) {
12391239
return true;
12401240
}
12411241
}

src/rpc/util.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ CPubKey AddrToPubKey(const FillableSigningProvider& keystore, const std::string&
197197
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("%s does not refer to a key", addr_in));
198198
}
199199
CPubKey vchPubKey;
200-
if (!keystore.GetPubKey(CKeyID(*pkhash), vchPubKey)) {
200+
if (!keystore.GetPubKey(ToKeyID(*pkhash), vchPubKey)) {
201201
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("no full public key for address %s", addr_in));
202202
}
203203
if (!vchPubKey.IsFullyValid()) {

src/script/sign.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
123123
}
124124
case TxoutType::SCRIPTHASH:
125125
h160 = uint160(vSolutions[0]);
126-
if (GetCScript(provider, sigdata, h160, scriptRet)) {
126+
if (GetCScript(provider, sigdata, CScriptID{h160}, scriptRet)) {
127127
ret.push_back(std::vector<unsigned char>(scriptRet.begin(), scriptRet.end()));
128128
return true;
129129
}

src/script/standard.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,19 @@ typedef std::vector<unsigned char> valtype;
1313
bool fAcceptDatacarrier = DEFAULT_ACCEPT_DATACARRIER;
1414
unsigned nMaxDatacarrierBytes = MAX_OP_RETURN_RELAY;
1515

16-
CScriptID::CScriptID(const CScript& in) : uint160(Hash160(in.begin(), in.end())) {}
16+
CScriptID::CScriptID(const CScript& in) : BaseHash(Hash160(in.begin(), in.end())) {}
17+
CScriptID::CScriptID(const ScriptHash& in) : BaseHash(static_cast<uint160>(in)) {}
1718

18-
ScriptHash::ScriptHash(const CScript& in) : uint160(Hash160(in.begin(), in.end())) {}
19+
ScriptHash::ScriptHash(const CScript& in) : BaseHash(Hash160(in.begin(), in.end())) {}
20+
ScriptHash::ScriptHash(const CScriptID& in) : BaseHash(static_cast<uint160>(in)) {}
1921

20-
PKHash::PKHash(const CPubKey& pubkey) : uint160(pubkey.GetID()) {}
22+
PKHash::PKHash(const CPubKey& pubkey) : BaseHash(pubkey.GetID()) {}
23+
PKHash::PKHash(const CKeyID& pubkey_id) : BaseHash(pubkey_id) {}
24+
25+
CKeyID ToKeyID(const PKHash& key_hash)
26+
{
27+
return CKeyID{static_cast<uint160>(key_hash)};
28+
}
2129

2230
const char* GetTxnOutputType(TxoutType t)
2331
{

src/script/standard.h

Lines changed: 75 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,77 @@ static const bool DEFAULT_ACCEPT_DATACARRIER = true;
1515

1616
class CKeyID;
1717
class CScript;
18+
struct ScriptHash;
19+
20+
template<typename HashType>
21+
class BaseHash
22+
{
23+
protected:
24+
HashType m_hash;
25+
26+
public:
27+
BaseHash() : m_hash() {}
28+
BaseHash(const HashType& in) : m_hash(in) {}
29+
30+
unsigned char* begin()
31+
{
32+
return m_hash.begin();
33+
}
34+
35+
const unsigned char* begin() const
36+
{
37+
return m_hash.begin();
38+
}
39+
40+
unsigned char* end()
41+
{
42+
return m_hash.end();
43+
}
44+
45+
const unsigned char* end() const
46+
{
47+
return m_hash.end();
48+
}
49+
50+
operator std::vector<unsigned char>() const
51+
{
52+
return std::vector<unsigned char>{m_hash.begin(), m_hash.end()};
53+
}
54+
55+
std::string ToString() const
56+
{
57+
return m_hash.ToString();
58+
}
59+
60+
bool operator==(const BaseHash<HashType>& other) const noexcept
61+
{
62+
return m_hash == other.m_hash;
63+
}
64+
65+
bool operator!=(const BaseHash<HashType>& other) const noexcept
66+
{
67+
return !(m_hash == other.m_hash);
68+
}
69+
70+
bool operator<(const BaseHash<HashType>& other) const noexcept
71+
{
72+
return m_hash < other.m_hash;
73+
}
74+
75+
size_t size() const
76+
{
77+
return m_hash.size();
78+
}
79+
};
1880

1981
/** A reference to a CScript: the Hash160 of its serialization (see script.h) */
20-
class CScriptID : public uint160
82+
class CScriptID : public BaseHash<uint160>
2183
{
2284
public:
23-
CScriptID() : uint160() {}
85+
CScriptID() : BaseHash() {}
2486
explicit CScriptID(const CScript& in);
25-
CScriptID(const uint160& in) : uint160(in) {}
87+
explicit CScriptID(const uint160& in) : BaseHash(in) {}
88+
explicit CScriptID(const ScriptHash& in);
2689
};
2790

2891
/**
@@ -67,20 +130,21 @@ class CNoDestination {
67130
friend bool operator<(const CNoDestination &a, const CNoDestination &b) { return true; }
68131
};
69132

70-
struct PKHash : public uint160
133+
struct PKHash : public BaseHash<uint160>
71134
{
72-
PKHash() : uint160() {}
73-
explicit PKHash(const uint160& hash) : uint160(hash) {}
135+
PKHash() : BaseHash() {}
136+
explicit PKHash(const uint160& hash) : BaseHash(hash) {}
74137
explicit PKHash(const CPubKey& pubkey);
75-
using uint160::uint160;
138+
explicit PKHash(const CKeyID& pubkey_id);
76139
};
140+
CKeyID ToKeyID(const PKHash& key_hash);
77141

78-
struct ScriptHash : public uint160
142+
struct ScriptHash : public BaseHash<uint160>
79143
{
80-
ScriptHash() : uint160() {}
81-
explicit ScriptHash(const uint160& hash) : uint160(hash) {}
144+
ScriptHash() : BaseHash() {}
145+
explicit ScriptHash(const uint160& hash) : BaseHash(hash) {}
82146
explicit ScriptHash(const CScript& script);
83-
using uint160::uint160;
147+
explicit ScriptHash(const CScriptID& script);
84148
};
85149

86150
/**

src/spork.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ bool CSporkManager::SetSporkAddress(const std::string& strAddress)
286286
LogPrintf("CSporkManager::SetSporkAddress -- Failed to parse spork address\n");
287287
return false;
288288
}
289-
setSporkPubKeyIDs.insert(CKeyID(*pkhash));
289+
setSporkPubKeyIDs.insert(ToKeyID(*pkhash));
290290
return true;
291291
}
292292

src/wallet/rpcdump.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ UniValue importprivkey(const JSONRPCRequest& request)
145145
}
146146

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

src/wallet/rpcwallet.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3564,7 +3564,7 @@ class DescribeWalletAddressVisitor
35643564
UniValue operator()(const CNoDestination &dest) const { return UniValue(UniValue::VOBJ); }
35653565

35663566
UniValue operator()(const PKHash& pkhash) const {
3567-
CKeyID keyID(pkhash);
3567+
CKeyID keyID{ToKeyID(pkhash)};
35683568
UniValue obj(UniValue::VOBJ);
35693569
CPubKey vchPubKey;
35703570
if (provider && provider->GetPubKey(keyID, vchPubKey)) {
@@ -3727,7 +3727,7 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
37273727
CHDChain hdChainCurrent;
37283728
LegacyScriptPubKeyMan* legacy_spk_man = pwallet->GetLegacyScriptPubKeyMan();
37293729
if (legacy_spk_man != nullptr) {
3730-
if (pkhash && legacy_spk_man->HaveHDKey(CKeyID(*pkhash), hdChainCurrent)) {
3730+
if (pkhash && legacy_spk_man->HaveHDKey(ToKeyID(*pkhash), hdChainCurrent)) {
37313731
ret.pushKV("hdchainid", hdChainCurrent.GetID().GetHex());
37323732
}
37333733
}

0 commit comments

Comments
 (0)