addresstype.cpp raw
1 // Copyright (c) 2023-present 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::ANCHOR: {
91 addressRet = PayToAnchor();
92 return true;
93 }
94 case TxoutType::WITNESS_UNKNOWN: {
95 addressRet = WitnessUnknown{vSolutions[0][0], vSolutions[1]};
96 return true;
97 }
98 case TxoutType::MULTISIG:
99 case TxoutType::NULL_DATA:
100 case TxoutType::NONSTANDARD:
101 addressRet = CNoDestination(scriptPubKey);
102 return false;
103 } // no default case, so the compiler can warn about missing cases
104 assert(false);
105 }
106
107 namespace {
108 class CScriptVisitor
109 {
110 public:
111 CScript operator()(const CNoDestination& dest) const
112 {
113 return dest.GetScript();
114 }
115
116 CScript operator()(const PubKeyDestination& dest) const
117 {
118 return CScript() << ToByteVector(dest.GetPubKey()) << OP_CHECKSIG;
119 }
120
121 CScript operator()(const PKHash& keyID) const
122 {
123 return CScript() << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
124 }
125
126 CScript operator()(const ScriptHash& scriptID) const
127 {
128 return CScript() << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL;
129 }
130
131 CScript operator()(const WitnessV0KeyHash& id) const
132 {
133 return CScript() << OP_0 << ToByteVector(id);
134 }
135
136 CScript operator()(const WitnessV0ScriptHash& id) const
137 {
138 return CScript() << OP_0 << ToByteVector(id);
139 }
140
141 CScript operator()(const WitnessV1Taproot& tap) const
142 {
143 return CScript() << OP_1 << ToByteVector(tap);
144 }
145
146 CScript operator()(const WitnessUnknown& id) const
147 {
148 return CScript() << CScript::EncodeOP_N(id.GetWitnessVersion()) << id.GetWitnessProgram();
149 }
150 };
151
152 class ValidDestinationVisitor
153 {
154 public:
155 bool operator()(const CNoDestination& dest) const { return false; }
156 bool operator()(const PubKeyDestination& dest) const { return false; }
157 bool operator()(const PKHash& dest) const { return true; }
158 bool operator()(const ScriptHash& dest) const { return true; }
159 bool operator()(const WitnessV0KeyHash& dest) const { return true; }
160 bool operator()(const WitnessV0ScriptHash& dest) const { return true; }
161 bool operator()(const WitnessV1Taproot& dest) const { return true; }
162 bool operator()(const WitnessUnknown& dest) const { return true; }
163 };
164 } // namespace
165
166 CScript GetScriptForDestination(const CTxDestination& dest)
167 {
168 return std::visit(CScriptVisitor(), dest);
169 }
170
171 bool IsValidDestination(const CTxDestination& dest) {
172 return std::visit(ValidDestinationVisitor(), dest);
173 }
174