diff options
Diffstat (limited to 'src/addresstype.cpp')
-rw-r--r-- | src/addresstype.cpp | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/src/addresstype.cpp b/src/addresstype.cpp new file mode 100644 index 0000000000..96428df846 --- /dev/null +++ b/src/addresstype.cpp @@ -0,0 +1,150 @@ +// Copyright (c) 2023 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php. + +#include <addresstype.h> +#include <script/script.h> +#include <script/standard.h> +#include <hash.h> +#include <pubkey.h> +#include <uint256.h> +#include <util/hash_type.h> + +#include <vector> + +typedef std::vector<unsigned char> valtype; + +ScriptHash::ScriptHash(const CScript& in) : BaseHash(Hash160(in)) {} +ScriptHash::ScriptHash(const CScriptID& in) : BaseHash(static_cast<uint160>(in)) {} + +PKHash::PKHash(const CPubKey& pubkey) : BaseHash(pubkey.GetID()) {} +PKHash::PKHash(const CKeyID& pubkey_id) : BaseHash(pubkey_id) {} + +WitnessV0KeyHash::WitnessV0KeyHash(const CPubKey& pubkey) : BaseHash(pubkey.GetID()) {} +WitnessV0KeyHash::WitnessV0KeyHash(const PKHash& pubkey_hash) : BaseHash(static_cast<uint160>(pubkey_hash)) {} + +CKeyID ToKeyID(const PKHash& key_hash) +{ + return CKeyID{static_cast<uint160>(key_hash)}; +} + +CKeyID ToKeyID(const WitnessV0KeyHash& key_hash) +{ + return CKeyID{static_cast<uint160>(key_hash)}; +} + +CScriptID ToScriptID(const ScriptHash& script_hash) +{ + return CScriptID{static_cast<uint160>(script_hash)}; +} + +WitnessV0ScriptHash::WitnessV0ScriptHash(const CScript& in) +{ + CSHA256().Write(in.data(), in.size()).Finalize(begin()); +} + +bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet) +{ + std::vector<valtype> vSolutions; + TxoutType whichType = Solver(scriptPubKey, vSolutions); + + switch (whichType) { + case TxoutType::PUBKEY: { + CPubKey pubKey(vSolutions[0]); + if (!pubKey.IsValid()) + return false; + + addressRet = PKHash(pubKey); + return true; + } + case TxoutType::PUBKEYHASH: { + addressRet = PKHash(uint160(vSolutions[0])); + return true; + } + case TxoutType::SCRIPTHASH: { + addressRet = ScriptHash(uint160(vSolutions[0])); + return true; + } + case TxoutType::WITNESS_V0_KEYHASH: { + WitnessV0KeyHash hash; + std::copy(vSolutions[0].begin(), vSolutions[0].end(), hash.begin()); + addressRet = hash; + return true; + } + case TxoutType::WITNESS_V0_SCRIPTHASH: { + WitnessV0ScriptHash hash; + std::copy(vSolutions[0].begin(), vSolutions[0].end(), hash.begin()); + addressRet = hash; + return true; + } + case TxoutType::WITNESS_V1_TAPROOT: { + WitnessV1Taproot tap; + std::copy(vSolutions[0].begin(), vSolutions[0].end(), tap.begin()); + addressRet = tap; + return true; + } + case TxoutType::WITNESS_UNKNOWN: { + WitnessUnknown unk; + unk.version = vSolutions[0][0]; + std::copy(vSolutions[1].begin(), vSolutions[1].end(), unk.program); + unk.length = vSolutions[1].size(); + addressRet = unk; + return true; + } + case TxoutType::MULTISIG: + case TxoutType::NULL_DATA: + case TxoutType::NONSTANDARD: + return false; + } // no default case, so the compiler can warn about missing cases + assert(false); +} + +namespace { +class CScriptVisitor +{ +public: + CScript operator()(const CNoDestination& dest) const + { + return CScript(); + } + + CScript operator()(const PKHash& keyID) const + { + return CScript() << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG; + } + + CScript operator()(const ScriptHash& scriptID) const + { + return CScript() << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL; + } + + CScript operator()(const WitnessV0KeyHash& id) const + { + return CScript() << OP_0 << ToByteVector(id); + } + + CScript operator()(const WitnessV0ScriptHash& id) const + { + return CScript() << OP_0 << ToByteVector(id); + } + + CScript operator()(const WitnessV1Taproot& tap) const + { + return CScript() << OP_1 << ToByteVector(tap); + } + + CScript operator()(const WitnessUnknown& id) const + { + return CScript() << CScript::EncodeOP_N(id.version) << std::vector<unsigned char>(id.program, id.program + id.length); + } +}; +} // namespace + +CScript GetScriptForDestination(const CTxDestination& dest) +{ + return std::visit(CScriptVisitor(), dest); +} + +bool IsValidDestination(const CTxDestination& dest) { + return dest.index() != 0; +} |