Allow CNoDestination to represent a raw script

Even if a script is not a standard destination type, it can still be
useful to have a CTxDestination that stores the script.
This commit is contained in:
Andrew Chow
2023-08-09 09:31:50 -04:00
parent 8dd067088d
commit 1a98a51c66
2 changed files with 28 additions and 14 deletions

View File

@@ -93,6 +93,7 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
case TxoutType::MULTISIG: case TxoutType::MULTISIG:
case TxoutType::NULL_DATA: case TxoutType::NULL_DATA:
case TxoutType::NONSTANDARD: case TxoutType::NONSTANDARD:
addressRet = CNoDestination(scriptPubKey);
return false; return false;
} // no default case, so the compiler can warn about missing cases } // no default case, so the compiler can warn about missing cases
assert(false); assert(false);
@@ -104,7 +105,7 @@ class CScriptVisitor
public: public:
CScript operator()(const CNoDestination& dest) const CScript operator()(const CNoDestination& dest) const
{ {
return CScript(); return dest.GetScript();
} }
CScript operator()(const PKHash& keyID) const CScript operator()(const PKHash& keyID) const

View File

@@ -14,9 +14,17 @@
#include <algorithm> #include <algorithm>
class CNoDestination { class CNoDestination {
private:
CScript m_script;
public: public:
friend bool operator==(const CNoDestination &a, const CNoDestination &b) { return true; } CNoDestination() = default;
friend bool operator<(const CNoDestination &a, const CNoDestination &b) { return true; } CNoDestination(const CScript& script) : m_script(script) {}
const CScript& GetScript() const { return m_script; }
friend bool operator==(const CNoDestination& a, const CNoDestination& b) { return a.GetScript() == b.GetScript(); }
friend bool operator<(const CNoDestination& a, const CNoDestination& b) { return a.GetScript() < b.GetScript(); }
}; };
struct PKHash : public BaseHash<uint160> struct PKHash : public BaseHash<uint160>
@@ -93,14 +101,14 @@ public:
}; };
/** /**
* A txout script template with a specific destination. It is either: * A txout script categorized into standard templates.
* * CNoDestination: no destination set * * CNoDestination: Optionally a script, no corresponding address.
* * PKHash: TxoutType::PUBKEYHASH destination (P2PKH) * * PKHash: TxoutType::PUBKEYHASH destination (P2PKH address)
* * ScriptHash: TxoutType::SCRIPTHASH destination (P2SH) * * ScriptHash: TxoutType::SCRIPTHASH destination (P2SH address)
* * WitnessV0ScriptHash: TxoutType::WITNESS_V0_SCRIPTHASH destination (P2WSH) * * WitnessV0ScriptHash: TxoutType::WITNESS_V0_SCRIPTHASH destination (P2WSH address)
* * WitnessV0KeyHash: TxoutType::WITNESS_V0_KEYHASH destination (P2WPKH) * * WitnessV0KeyHash: TxoutType::WITNESS_V0_KEYHASH destination (P2WPKH address)
* * WitnessV1Taproot: TxoutType::WITNESS_V1_TAPROOT destination (P2TR) * * WitnessV1Taproot: TxoutType::WITNESS_V1_TAPROOT destination (P2TR address)
* * WitnessUnknown: TxoutType::WITNESS_UNKNOWN destination (P2W???) * * WitnessUnknown: TxoutType::WITNESS_UNKNOWN destination (P2W??? address)
* A CTxDestination is the internal data type encoded in a bitcoin address * A CTxDestination is the internal data type encoded in a bitcoin address
*/ */
using CTxDestination = std::variant<CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown>; using CTxDestination = std::variant<CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown>;
@@ -109,9 +117,14 @@ using CTxDestination = std::variant<CNoDestination, PKHash, ScriptHash, WitnessV
bool IsValidDestination(const CTxDestination& dest); bool IsValidDestination(const CTxDestination& dest);
/** /**
* Parse a standard scriptPubKey for the destination address. Assigns result to * Parse a scriptPubKey for the destination.
* the addressRet parameter and returns true if successful. Currently only works for P2PK, *
* P2PKH, P2SH, P2WPKH, and P2WSH scripts. * For standard scripts that have addresses (and P2PK as an exception), a corresponding CTxDestination
* is assigned to addressRet.
* For all other scripts. addressRet is assigned as a CNoDestination containing the scriptPubKey.
*
* Returns true for standard destinations - P2PK, P2PKH, P2SH, P2WPKH, P2WSH, and P2TR scripts.
* Returns false for non-standard destinations - P2PK with invalid pubkeys, P2W???, bare multisig, null data, and nonstandard scripts.
*/ */
bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet); bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet);