Skip to content

Commit

Permalink
Port address type
Browse files Browse the repository at this point in the history
  • Loading branch information
timemarkovqtum committed Mar 19, 2024
1 parent 26e528d commit 2def8e8
Show file tree
Hide file tree
Showing 3 changed files with 344 additions and 5 deletions.
102 changes: 98 additions & 4 deletions src/addresstype.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
#include <script/solver.h>
#include <uint256.h>
#include <util/hash_type.h>
#include <qtum/qtumstate.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} {}
Expand Down Expand Up @@ -46,16 +46,23 @@ WitnessV0ScriptHash::WitnessV0ScriptHash(const CScript& in)
CSHA256().Write(in.data(), in.size()).Finalize(begin());
}

bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet, TxoutType* typeRet)
bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet, TxoutType* typeRet, bool convertPublicKeyToHash)
{
std::vector<valtype> vSolutions;
TxoutType whichType = Solver(scriptPubKey, vSolutions);

if(typeRet){
*typeRet = whichType;
}

switch (whichType) {
case TxoutType::PUBKEY: {
CPubKey pubKey(vSolutions[0]);
if (!pubKey.IsValid()) {
addressRet = CNoDestination(scriptPubKey);
} else if (convertPublicKeyToHash) {
addressRet = PKHash(pubKey);
return true;
} else {
addressRet = PubKeyDestination(pubKey);
}
Expand Down Expand Up @@ -94,6 +101,10 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet,
case TxoutType::MULTISIG:
case TxoutType::NULL_DATA:
case TxoutType::NONSTANDARD:
case TxoutType::CREATE_SENDER:
case TxoutType::CALL_SENDER:
case TxoutType::CREATE:
case TxoutType::CALL:
addressRet = CNoDestination(scriptPubKey);
return false;
} // no default case, so the compiler can warn about missing cases
Expand Down Expand Up @@ -170,9 +181,92 @@ bool IsValidDestination(const CTxDestination& dest) {

PKHash ExtractPublicKeyHash(const CScript& scriptPubKey, bool* OK)
{
return {};
if(OK) *OK = false;
CTxDestination address;
TxoutType txType=TxoutType::NONSTANDARD;
if(ExtractDestination(scriptPubKey, address, &txType, true)){
if ((txType == TxoutType::PUBKEY || txType == TxoutType::PUBKEYHASH) && std::holds_alternative<PKHash>(address)) {
if(OK) *OK = true;
return std::get<PKHash>(address);
}
}

return PKHash();
}

bool IsValidContractSenderAddress(const CTxDestination& dest) {
return {};
return std::holds_alternative<PKHash>(dest);
}

valtype DataVisitor::operator()(const CNoDestination& noDest) const { return valtype(); }
valtype DataVisitor::operator()(const PKHash& keyID) const { return valtype(keyID.begin(), keyID.end()); }
valtype DataVisitor::operator()(const PubKeyDestination& pubKey) const {
PKHash keyID(pubKey.GetPubKey());
return valtype(keyID.begin(), keyID.end());
}
valtype DataVisitor::operator()(const ScriptHash& scriptID) const { return valtype(scriptID.begin(), scriptID.end()); }
valtype DataVisitor::operator()(const WitnessV0ScriptHash& witnessScriptHash) const { return valtype(witnessScriptHash.begin(), witnessScriptHash.end()); }
valtype DataVisitor::operator()(const WitnessV0KeyHash& witnessKeyHash) const { return valtype(witnessKeyHash.begin(), witnessKeyHash.end()); }
valtype DataVisitor::operator()(const WitnessV1Taproot& witnessTaproot) const { return valtype(witnessTaproot.begin(), witnessTaproot.end()); }
valtype DataVisitor::operator()(const WitnessUnknown&) const { return valtype(); }

bool ExtractDestination(const COutPoint& prevout, const CScript& scriptPubKey, CTxDestination& addressRet, TxoutType* typeRet)
{
std::vector<valtype> vSolutions;
TxoutType whichType = Solver(scriptPubKey, vSolutions);

if(typeRet){
*typeRet = whichType;
}


if (whichType == TxoutType::PUBKEY)
{
CPubKey pubKey(vSolutions[0]);
if (!pubKey.IsValid())
return false;

addressRet = PKHash(pubKey);
return true;
}
else if (whichType == TxoutType::PUBKEYHASH)
{
addressRet = PKHash(uint160(vSolutions[0]));
return true;
}
else if (whichType == TxoutType::SCRIPTHASH)
{
addressRet = ScriptHash(uint160(vSolutions[0]));
return true;
}
else if(whichType == TxoutType::CALL){
addressRet = PKHash(uint160(vSolutions[0]));
return true;
}
else if(whichType == TxoutType::WITNESS_V0_KEYHASH)
{
addressRet = WitnessV0KeyHash(uint160(vSolutions[0]));
return true;
}
else if(whichType == TxoutType::WITNESS_V0_SCRIPTHASH)
{
addressRet = WitnessV0ScriptHash(uint256(vSolutions[0]));
return true;
}
else if(whichType == TxoutType::WITNESS_V1_TAPROOT)
{
WitnessV1Taproot tap;
std::copy(vSolutions[0].begin(), vSolutions[0].end(), tap.begin());
addressRet = tap;
return true;
}
else if (whichType == TxoutType::WITNESS_UNKNOWN) {
addressRet = WitnessUnknown{vSolutions[0][0], vSolutions[1]};
return true;
}
else if (whichType == TxoutType::CREATE) {
addressRet = PKHash(uint160(QtumState::createQtumAddress(uintToh256(prevout.hash), prevout.n).asBytes()));
return true;
}
return false;
}
19 changes: 18 additions & 1 deletion src/addresstype.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@
#include <script/script.h>
#include <uint256.h>
#include <util/hash_type.h>
#include <primitives/transaction.h>

#include <variant>
#include <algorithm>
enum class TxoutType;

typedef std::vector<unsigned char> valtype;

class CNoDestination
{
private:
Expand Down Expand Up @@ -142,7 +145,7 @@ bool IsValidDestination(const CTxDestination& dest);
* Returns true for standard destinations with addresses - P2PKH, P2SH, P2WPKH, P2WSH, P2TR and P2W??? scripts.
* Returns false for non-standard destinations and those without addresses - P2PK, bare multisig, null data, and nonstandard scripts.
*/
bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet, TxoutType* typeRet = NULL);
bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet, TxoutType* typeRet = NULL, bool convertPublicKeyToHash = false);

/**
* Generate a Bitcoin scriptPubKey for the given CTxDestination. Returns a P2PKH
Expand All @@ -168,4 +171,18 @@ bool IsValidContractSenderAddress(const CTxDestination& dest);

PKHash ExtractPublicKeyHash(const CScript& scriptPubKey, bool* OK = nullptr);

struct DataVisitor
{
valtype operator()(const CNoDestination& noDest) const;
valtype operator()(const PKHash& keyID) const;
valtype operator()(const PubKeyDestination& pubKey) const;
valtype operator()(const ScriptHash& scriptID) const;
valtype operator()(const WitnessV0ScriptHash& witnessScriptHash) const;
valtype operator()(const WitnessV0KeyHash& witnessKeyHash) const;
valtype operator()(const WitnessV1Taproot& witnessTaproot) const;
valtype operator()(const WitnessUnknown& witnessUnknown) const;
};

bool ExtractDestination(const COutPoint& prevout, const CScript& scriptPubKey, CTxDestination& addressRet, TxoutType* typeRet = NULL);

#endif // BITCOIN_ADDRESSTYPE_H
Loading

0 comments on commit 2def8e8

Please sign in to comment.