Branch data Line data Source code
1 : : // Copyright (c) 2023 The Bitcoin Core developers 2 : : // Distributed under the MIT software license, see the accompanying 3 : : // file COPYING or https://www.opensource.org/licenses/mit-license.php. 4 : : 5 : : #include <addresstype.h> 6 : : 7 : : #include <crypto/sha256.h> 8 : : #include <hash.h> 9 : : #include <pubkey.h> 10 : : #include <script/script.h> 11 : : #include <script/solver.h> 12 : : #include <uint256.h> 13 : : #include <util/hash_type.h> 14 : : 15 : : #include <cassert> 16 : : #include <vector> 17 : : 18 : : typedef std::vector<unsigned char> valtype; 19 : : 20 : 50 : ScriptHash::ScriptHash(const CScript& in) : BaseHash(Hash160(in)) {} 21 : 0 : ScriptHash::ScriptHash(const CScriptID& in) : BaseHash{in} {} 22 : : 23 : 0 : PKHash::PKHash(const CPubKey& pubkey) : BaseHash(pubkey.GetID()) {} 24 : 14 : PKHash::PKHash(const CKeyID& pubkey_id) : BaseHash(pubkey_id) {} 25 : : 26 : 0 : WitnessV0KeyHash::WitnessV0KeyHash(const CPubKey& pubkey) : BaseHash(pubkey.GetID()) {} 27 : 0 : WitnessV0KeyHash::WitnessV0KeyHash(const PKHash& pubkey_hash) : BaseHash{pubkey_hash} {} 28 : : 29 : 0 : CKeyID ToKeyID(const PKHash& key_hash) 30 : : { 31 : 0 : return CKeyID{uint160{key_hash}}; 32 : : } 33 : : 34 : 0 : CKeyID ToKeyID(const WitnessV0KeyHash& key_hash) 35 : : { 36 : 0 : return CKeyID{uint160{key_hash}}; 37 : : } 38 : : 39 : 0 : CScriptID ToScriptID(const ScriptHash& script_hash) 40 : : { 41 : 0 : return CScriptID{uint160{script_hash}}; 42 : : } 43 : : 44 : 254 : WitnessV0ScriptHash::WitnessV0ScriptHash(const CScript& in) 45 : : { 46 : 254 : CSHA256().Write(in.data(), in.size()).Finalize(begin()); 47 : 254 : } 48 : : 49 : 108 : bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet) 50 : : { 51 : 108 : std::vector<valtype> vSolutions; 52 [ + - ]: 108 : TxoutType whichType = Solver(scriptPubKey, vSolutions); 53 : : 54 [ + - - - : 108 : switch (whichType) { - - + - + ] 55 : : case TxoutType::PUBKEY: { 56 [ + - ][ + - ]: 2 : CPubKey pubKey(vSolutions[0]); 57 [ + - ][ - + ]: 2 : if (!pubKey.IsValid()) { 58 [ # # ]: 0 : addressRet = CNoDestination(scriptPubKey); 59 : 0 : } else { 60 [ + - ]: 2 : addressRet = PubKeyDestination(pubKey); 61 : : } 62 : 2 : return false; 63 : : } 64 : : case TxoutType::PUBKEYHASH: { 65 [ # # ][ # # ]: 0 : addressRet = PKHash(uint160(vSolutions[0])); [ # # ] 66 : 0 : return true; 67 : : } 68 : : case TxoutType::SCRIPTHASH: { 69 [ # # ][ # # ]: 0 : addressRet = ScriptHash(uint160(vSolutions[0])); [ # # ] 70 : 0 : return true; 71 : : } 72 : : case TxoutType::WITNESS_V0_KEYHASH: { 73 [ # # ]: 0 : WitnessV0KeyHash hash; 74 [ # # ][ # # ]: 0 : std::copy(vSolutions[0].begin(), vSolutions[0].end(), hash.begin()); 75 : 0 : addressRet = hash; 76 : 0 : return true; 77 : : } 78 : : case TxoutType::WITNESS_V0_SCRIPTHASH: { 79 [ # # ]: 0 : WitnessV0ScriptHash hash; 80 [ # # ][ # # ]: 0 : std::copy(vSolutions[0].begin(), vSolutions[0].end(), hash.begin()); 81 : 0 : addressRet = hash; 82 : 0 : return true; 83 : : } 84 : : case TxoutType::WITNESS_V1_TAPROOT: { 85 [ # # ]: 0 : WitnessV1Taproot tap; 86 [ # # ][ # # ]: 0 : std::copy(vSolutions[0].begin(), vSolutions[0].end(), tap.begin()); 87 : 0 : addressRet = tap; 88 : 0 : return true; 89 : : } 90 : : case TxoutType::WITNESS_UNKNOWN: { 91 [ + - ]: 10 : addressRet = WitnessUnknown{vSolutions[0][0], vSolutions[1]}; 92 : 10 : return true; 93 : : } 94 : : case TxoutType::MULTISIG: 95 : : case TxoutType::NULL_DATA: 96 : : case TxoutType::NONSTANDARD: 97 [ + - ]: 96 : addressRet = CNoDestination(scriptPubKey); 98 : 96 : return false; 99 : : } // no default case, so the compiler can warn about missing cases 100 : 0 : assert(false); 101 : 108 : } 102 : : 103 : : namespace { 104 : : class CScriptVisitor 105 : : { 106 : : public: 107 : 0 : CScript operator()(const CNoDestination& dest) const 108 : : { 109 : 0 : return dest.GetScript(); 110 : : } 111 : : 112 : 0 : CScript operator()(const PubKeyDestination& dest) const 113 : : { 114 [ # # ][ # # ]: 0 : return CScript() << ToByteVector(dest.GetPubKey()) << OP_CHECKSIG; [ # # ][ # # ] [ # # ] 115 : 0 : } 116 : : 117 : 14 : CScript operator()(const PKHash& keyID) const 118 : : { 119 [ + - ][ + - ]: 14 : return CScript() << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG; [ + - ][ + - ] [ + - ][ + - ] [ + - ] 120 : 0 : } 121 : : 122 : 50 : CScript operator()(const ScriptHash& scriptID) const 123 : : { 124 [ + - ][ + - ]: 50 : return CScript() << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL; [ + - ][ + - ] [ + - ] 125 : 0 : } 126 : : 127 : 8 : CScript operator()(const WitnessV0KeyHash& id) const 128 : : { 129 [ + - ][ + - ]: 8 : return CScript() << OP_0 << ToByteVector(id); [ + - ][ + - ] 130 : 0 : } 131 : : 132 : 254 : CScript operator()(const WitnessV0ScriptHash& id) const 133 : : { 134 [ + - ][ + - ]: 254 : return CScript() << OP_0 << ToByteVector(id); [ + - ][ + - ] 135 : 0 : } 136 : : 137 : 174 : CScript operator()(const WitnessV1Taproot& tap) const 138 : : { 139 [ + - ][ + - ]: 174 : return CScript() << OP_1 << ToByteVector(tap); [ + - ][ + - ] 140 : 0 : } 141 : : 142 : 5 : CScript operator()(const WitnessUnknown& id) const 143 : : { 144 [ + - ][ + - ]: 5 : return CScript() << CScript::EncodeOP_N(id.GetWitnessVersion()) << id.GetWitnessProgram(); [ + - ][ + - ] [ + - ][ + - ] 145 : 0 : } 146 : : }; 147 : : 148 : : class ValidDestinationVisitor 149 : : { 150 : : public: 151 : 27 : bool operator()(const CNoDestination& dest) const { return false; } 152 : 0 : bool operator()(const PubKeyDestination& dest) const { return false; } 153 : 0 : bool operator()(const PKHash& dest) const { return true; } 154 : 0 : bool operator()(const ScriptHash& dest) const { return true; } 155 : 0 : bool operator()(const WitnessV0KeyHash& dest) const { return true; } 156 : 0 : bool operator()(const WitnessV0ScriptHash& dest) const { return true; } 157 : 0 : bool operator()(const WitnessV1Taproot& dest) const { return true; } 158 : 0 : bool operator()(const WitnessUnknown& dest) const { return true; } 159 : : }; 160 : : } // namespace 161 : : 162 : 505 : CScript GetScriptForDestination(const CTxDestination& dest) 163 : : { 164 : 505 : return std::visit(CScriptVisitor(), dest); 165 : : } 166 : : 167 : 27 : bool IsValidDestination(const CTxDestination& dest) { 168 : 27 : return std::visit(ValidDestinationVisitor(), dest); 169 : : }