| 143 | }; |
| 144 | |
| 145 | CTxDestination DecodeDestination(const std::string& str, const CChainParams& params, const bool for_parent, std::string& error_str, std::vector<int>* error_locations) |
| 146 | { |
| 147 | // ELEMENTS: special case nulldata as "null" |
| 148 | if (str == "null") return NullData{}; |
| 149 | |
| 150 | std::vector<unsigned char> data; |
| 151 | size_t pk_size = CPubKey::COMPRESSED_SIZE; |
| 152 | uint160 hash; |
| 153 | error_str = ""; |
| 154 | |
| 155 | bool is_bech32 = !(bech32::Decode(str).encoding == bech32::Encoding::INVALID); |
| 156 | bool is_blech32 = !(blech32::Decode(str).encoding == blech32::Encoding::INVALID); |
| 157 | |
| 158 | // Note this will be false if it is a valid Bech32 address for a different network |
| 159 | bool is_bech32_hrp = (ToLower(str.substr(0, params.Bech32HRP().size())) == params.Bech32HRP()); |
| 160 | bool is_blech32_hrp = (ToLower(str.substr(0, params.Blech32HRP().size())) == params.Blech32HRP()); |
| 161 | |
| 162 | if (!is_bech32 && !is_blech32 && !is_bech32_hrp && !is_blech32_hrp && DecodeBase58Check(str, data, 55)) { |
| 163 | // base58-encoded Bitcoin addresses. |
| 164 | // Public-key-hash-addresses have version 0 (or 111 testnet). |
| 165 | // The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key. |
| 166 | |
| 167 | // Blinded addresses have two prefixes: first the blinded one, then the traditional one. |
| 168 | const std::vector<unsigned char>& blinded_prefix = params.Base58Prefix(CChainParams::BLINDED_ADDRESS); |
| 169 | |
| 170 | CChainParams::Base58Type type_pkh = for_parent ? CChainParams::PARENT_PUBKEY_ADDRESS : CChainParams::PUBKEY_ADDRESS; |
| 171 | const std::vector<unsigned char>& pubkey_prefix = params.Base58Prefix(type_pkh); |
| 172 | if (data.size() == hash.size() + pubkey_prefix.size() && std::equal(pubkey_prefix.begin(), pubkey_prefix.end(), data.begin())) { |
| 173 | std::copy(data.begin() + pubkey_prefix.size(), data.end(), hash.begin()); |
| 174 | return PKHash(CKeyID(hash)); |
| 175 | } else if (data.size() == hash.size() + blinded_prefix.size() + pubkey_prefix.size() + pk_size && |
| 176 | std::equal(blinded_prefix.begin(), blinded_prefix.end(), data.begin()) && |
| 177 | std::equal(pubkey_prefix.begin(), pubkey_prefix.end(), data.begin() + blinded_prefix.size())) { |
| 178 | auto payload_start = data.begin() + blinded_prefix.size() + pubkey_prefix.size(); |
| 179 | CPubKey pubkey; |
| 180 | pubkey.Set(payload_start, payload_start + pk_size); |
| 181 | std::copy(payload_start + pk_size, data.end(), hash.begin()); |
| 182 | return PKHash(CKeyID(hash), pubkey); |
| 183 | } |
| 184 | |
| 185 | // Script-hash-addresses have version 5 (or 196 testnet). |
| 186 | // The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script. |
| 187 | CChainParams::Base58Type type_sh = for_parent ? CChainParams::PARENT_SCRIPT_ADDRESS : CChainParams::SCRIPT_ADDRESS; |
| 188 | const std::vector<unsigned char>& script_prefix = params.Base58Prefix(type_sh); |
| 189 | if (data.size() == hash.size() + script_prefix.size() && std::equal(script_prefix.begin(), script_prefix.end(), data.begin())) { |
| 190 | std::copy(data.begin() + script_prefix.size(), data.end(), hash.begin()); |
| 191 | return ScriptHash(CScriptID(hash)); |
| 192 | } else if (data.size() == hash.size() + blinded_prefix.size() + pubkey_prefix.size() + pk_size && |
| 193 | std::equal(blinded_prefix.begin(), blinded_prefix.end(), data.begin()) && |
| 194 | std::equal(script_prefix.begin(), script_prefix.end(), data.begin() + blinded_prefix.size())) { |
| 195 | auto payload_start = data.begin() + blinded_prefix.size() + script_prefix.size(); |
| 196 | CPubKey pubkey; |
| 197 | pubkey.Set(payload_start, payload_start + pk_size); |
| 198 | std::copy(payload_start + pk_size, data.end(), hash.begin()); |
| 199 | return ScriptHash(CScriptID(hash), pubkey); |
| 200 | } |
| 201 | |
| 202 | // If the prefix of data matches either the script or pubkey prefix, the length must have been wrong |