addresstype.cpp
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 ScriptHash::ScriptHash(const CScript& in) : BaseHash(Hash160(in)) {} 21 ScriptHash::ScriptHash(const CScriptID& in) : BaseHash{in} {} 22 23 PKHash::PKHash(const CPubKey& pubkey) : BaseHash(pubkey.GetID()) {} 24 PKHash::PKHash(const CKeyID& pubkey_id) : BaseHash(pubkey_id) {} 25 26 WitnessV0KeyHash::WitnessV0KeyHash(const CPubKey& pubkey) : BaseHash(pubkey.GetID()) {} 27 WitnessV0KeyHash::WitnessV0KeyHash(const PKHash& pubkey_hash) : BaseHash{pubkey_hash} {} 28 29 CKeyID ToKeyID(const PKHash& key_hash) 30 { 31 return CKeyID{uint160{key_hash}}; 32 } 33 34 CKeyID ToKeyID(const WitnessV0KeyHash& key_hash) 35 { 36 return CKeyID{uint160{key_hash}}; 37 } 38 39 CScriptID ToScriptID(const ScriptHash& script_hash) 40 { 41 return CScriptID{uint160{script_hash}}; 42 } 43 44 WitnessV0ScriptHash::WitnessV0ScriptHash(const CScript& in) 45 { 46 CSHA256().Write(in.data(), in.size()).Finalize(begin()); 47 } 48 49 bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet) 50 { 51 std::vector<valtype> vSolutions; 52 TxoutType whichType = Solver(scriptPubKey, vSolutions); 53 54 switch (whichType) { 55 case TxoutType::PUBKEY: { 56 CPubKey pubKey(vSolutions[0]); 57 if (!pubKey.IsValid()) { 58 addressRet = CNoDestination(scriptPubKey); 59 } else { 60 addressRet = PubKeyDestination(pubKey); 61 } 62 return false; 63 } 64 case TxoutType::PUBKEYHASH: { 65 addressRet = PKHash(uint160(vSolutions[0])); 66 return true; 67 } 68 case TxoutType::SCRIPTHASH: { 69 addressRet = ScriptHash(uint160(vSolutions[0])); 70 return true; 71 } 72 case TxoutType::WITNESS_V0_KEYHASH: { 73 WitnessV0KeyHash hash; 74 std::copy(vSolutions[0].begin(), vSolutions[0].end(), hash.begin()); 75 addressRet = hash; 76 return true; 77 } 78 case TxoutType::WITNESS_V0_SCRIPTHASH: { 79 WitnessV0ScriptHash hash; 80 std::copy(vSolutions[0].begin(), vSolutions[0].end(), hash.begin()); 81 addressRet = hash; 82 return true; 83 } 84 case TxoutType::WITNESS_V1_TAPROOT: { 85 WitnessV1Taproot tap; 86 std::copy(vSolutions[0].begin(), vSolutions[0].end(), tap.begin()); 87 addressRet = tap; 88 return true; 89 } 90 case TxoutType::WITNESS_UNKNOWN: { 91 addressRet = WitnessUnknown{vSolutions[0][0], vSolutions[1]}; 92 return true; 93 } 94 case TxoutType::MULTISIG: 95 case TxoutType::NULL_DATA: 96 case TxoutType::NONSTANDARD: 97 addressRet = CNoDestination(scriptPubKey); 98 return false; 99 } // no default case, so the compiler can warn about missing cases 100 assert(false); 101 } 102 103 namespace { 104 class CScriptVisitor 105 { 106 public: 107 CScript operator()(const CNoDestination& dest) const 108 { 109 return dest.GetScript(); 110 } 111 112 CScript operator()(const PubKeyDestination& dest) const 113 { 114 return CScript() << ToByteVector(dest.GetPubKey()) << OP_CHECKSIG; 115 } 116 117 CScript operator()(const PKHash& keyID) const 118 { 119 return CScript() << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG; 120 } 121 122 CScript operator()(const ScriptHash& scriptID) const 123 { 124 return CScript() << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL; 125 } 126 127 CScript operator()(const WitnessV0KeyHash& id) const 128 { 129 return CScript() << OP_0 << ToByteVector(id); 130 } 131 132 CScript operator()(const WitnessV0ScriptHash& id) const 133 { 134 return CScript() << OP_0 << ToByteVector(id); 135 } 136 137 CScript operator()(const WitnessV1Taproot& tap) const 138 { 139 return CScript() << OP_1 << ToByteVector(tap); 140 } 141 142 CScript operator()(const WitnessUnknown& id) const 143 { 144 return CScript() << CScript::EncodeOP_N(id.GetWitnessVersion()) << id.GetWitnessProgram(); 145 } 146 }; 147 148 class ValidDestinationVisitor 149 { 150 public: 151 bool operator()(const CNoDestination& dest) const { return false; } 152 bool operator()(const PubKeyDestination& dest) const { return false; } 153 bool operator()(const PKHash& dest) const { return true; } 154 bool operator()(const ScriptHash& dest) const { return true; } 155 bool operator()(const WitnessV0KeyHash& dest) const { return true; } 156 bool operator()(const WitnessV0ScriptHash& dest) const { return true; } 157 bool operator()(const WitnessV1Taproot& dest) const { return true; } 158 bool operator()(const WitnessUnknown& dest) const { return true; } 159 }; 160 } // namespace 161 162 CScript GetScriptForDestination(const CTxDestination& dest) 163 { 164 return std::visit(CScriptVisitor(), dest); 165 } 166 167 bool IsValidDestination(const CTxDestination& dest) { 168 return std::visit(ValidDestinationVisitor(), dest); 169 }