bitcoin/src/addresstype.cpp

154 lines
4.2 KiB
C++
Raw Normal View History

// 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>
2023-08-17 14:09:38 +02:00
#include <crypto/sha256.h>
#include <hash.h>
#include <pubkey.h>
2023-08-17 14:09:38 +02:00
#include <script/script.h>
#include <script/solver.h>
#include <uint256.h>
#include <util/hash_type.h>
2023-08-17 14:09:38 +02:00
#include <cassert>
#include <vector>
typedef std::vector<unsigned char> valtype;
ScriptHash::ScriptHash(const CScript& in) : BaseHash(Hash160(in)) {}
2023-08-17 14:39:07 +02:00
ScriptHash::ScriptHash(const CScriptID& in) : BaseHash{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()) {}
2023-08-17 14:39:07 +02:00
WitnessV0KeyHash::WitnessV0KeyHash(const PKHash& pubkey_hash) : BaseHash{pubkey_hash} {}
CKeyID ToKeyID(const PKHash& key_hash)
{
2023-08-17 14:39:07 +02:00
return CKeyID{uint160{key_hash}};
}
CKeyID ToKeyID(const WitnessV0KeyHash& key_hash)
{
2023-08-17 14:39:07 +02:00
return CKeyID{uint160{key_hash}};
}
CScriptID ToScriptID(const ScriptHash& script_hash)
{
2023-08-17 14:39:07 +02:00
return CScriptID{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;
}