mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-10 11:57:28 -03:00
07d3bdf4eb
P2PK scripts are not PKHash destinations, they should have their own type. This also results in no longer showing a p2pkh address for p2pk outputs. However for backwards compatibility, ListCoinst will still do this conversion.
169 lines
4.9 KiB
C++
169 lines
4.9 KiB
C++
// 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 <crypto/sha256.h>
|
|
#include <hash.h>
|
|
#include <pubkey.h>
|
|
#include <script/script.h>
|
|
#include <script/solver.h>
|
|
#include <uint256.h>
|
|
#include <util/hash_type.h>
|
|
|
|
#include <cassert>
|
|
#include <vector>
|
|
|
|
typedef std::vector<unsigned char> valtype;
|
|
|
|
ScriptHash::ScriptHash(const CScript& in) : BaseHash(Hash160(in)) {}
|
|
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()) {}
|
|
WitnessV0KeyHash::WitnessV0KeyHash(const PKHash& pubkey_hash) : BaseHash{pubkey_hash} {}
|
|
|
|
CKeyID ToKeyID(const PKHash& key_hash)
|
|
{
|
|
return CKeyID{uint160{key_hash}};
|
|
}
|
|
|
|
CKeyID ToKeyID(const WitnessV0KeyHash& key_hash)
|
|
{
|
|
return CKeyID{uint160{key_hash}};
|
|
}
|
|
|
|
CScriptID ToScriptID(const ScriptHash& script_hash)
|
|
{
|
|
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()) {
|
|
addressRet = CNoDestination(scriptPubKey);
|
|
} else {
|
|
addressRet = PubKeyDestination(pubKey);
|
|
}
|
|
return false;
|
|
}
|
|
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: {
|
|
addressRet = WitnessUnknown{vSolutions[0][0], vSolutions[1]};
|
|
return true;
|
|
}
|
|
case TxoutType::MULTISIG:
|
|
case TxoutType::NULL_DATA:
|
|
case TxoutType::NONSTANDARD:
|
|
addressRet = CNoDestination(scriptPubKey);
|
|
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 dest.GetScript();
|
|
}
|
|
|
|
CScript operator()(const PubKeyDestination& dest) const
|
|
{
|
|
return CScript() << ToByteVector(dest.GetPubKey()) << OP_CHECKSIG;
|
|
}
|
|
|
|
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.GetWitnessVersion()) << id.GetWitnessProgram();
|
|
}
|
|
};
|
|
|
|
class ValidDestinationVisitor
|
|
{
|
|
public:
|
|
bool operator()(const CNoDestination& dest) const { return false; }
|
|
bool operator()(const PubKeyDestination& dest) const { return false; }
|
|
bool operator()(const PKHash& dest) const { return true; }
|
|
bool operator()(const ScriptHash& dest) const { return true; }
|
|
bool operator()(const WitnessV0KeyHash& dest) const { return true; }
|
|
bool operator()(const WitnessV0ScriptHash& dest) const { return true; }
|
|
bool operator()(const WitnessV1Taproot& dest) const { return true; }
|
|
bool operator()(const WitnessUnknown& dest) const { return true; }
|
|
};
|
|
} // namespace
|
|
|
|
CScript GetScriptForDestination(const CTxDestination& dest)
|
|
{
|
|
return std::visit(CScriptVisitor(), dest);
|
|
}
|
|
|
|
bool IsValidDestination(const CTxDestination& dest) {
|
|
return std::visit(ValidDestinationVisitor(), dest);
|
|
}
|