aboutsummaryrefslogtreecommitdiff
path: root/src/script
diff options
context:
space:
mode:
Diffstat (limited to 'src/script')
-rw-r--r--src/script/descriptor.cpp18
-rw-r--r--src/script/sign.cpp60
-rw-r--r--src/script/signingprovider.cpp6
-rw-r--r--src/script/standard.cpp96
-rw-r--r--src/script/standard.h149
5 files changed, 205 insertions, 124 deletions
diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp
index 7a5421ab6f..5fa128d62d 100644
--- a/src/script/descriptor.cpp
+++ b/src/script/descriptor.cpp
@@ -235,7 +235,7 @@ public:
}
bool IsRange() const override { return false; }
size_t GetSize() const override { return m_pubkey.size(); }
- std::string ToString() const override { return HexStr(m_pubkey.begin(), m_pubkey.end()); }
+ std::string ToString() const override { return HexStr(m_pubkey); }
bool ToPrivateString(const SigningProvider& arg, std::string& ret) const override
{
CKey key;
@@ -583,7 +583,7 @@ class RawDescriptor final : public DescriptorImpl
{
const CScript m_script;
protected:
- std::string ToStringExtra() const override { return HexStr(m_script.begin(), m_script.end()); }
+ std::string ToStringExtra() const override { return HexStr(m_script); }
std::vector<CScript> MakeScripts(const std::vector<CPubKey>&, const CScript*, FlatSigningProvider&) const override { return Vector(m_script); }
public:
RawDescriptor(CScript script) : DescriptorImpl({}, {}, "raw"), m_script(std::move(script)) {}
@@ -985,15 +985,15 @@ std::unique_ptr<PubkeyProvider> InferPubkey(const CPubKey& pubkey, ParseScriptCo
std::unique_ptr<DescriptorImpl> InferScript(const CScript& script, ParseScriptContext ctx, const SigningProvider& provider)
{
std::vector<std::vector<unsigned char>> data;
- txnouttype txntype = Solver(script, data);
+ TxoutType txntype = Solver(script, data);
- if (txntype == TX_PUBKEY) {
+ if (txntype == TxoutType::PUBKEY) {
CPubKey pubkey(data[0].begin(), data[0].end());
if (pubkey.IsValid()) {
return MakeUnique<PKDescriptor>(InferPubkey(pubkey, ctx, provider));
}
}
- if (txntype == TX_PUBKEYHASH) {
+ if (txntype == TxoutType::PUBKEYHASH) {
uint160 hash(data[0]);
CKeyID keyid(hash);
CPubKey pubkey;
@@ -1001,7 +1001,7 @@ std::unique_ptr<DescriptorImpl> InferScript(const CScript& script, ParseScriptCo
return MakeUnique<PKHDescriptor>(InferPubkey(pubkey, ctx, provider));
}
}
- if (txntype == TX_WITNESS_V0_KEYHASH && ctx != ParseScriptContext::P2WSH) {
+ if (txntype == TxoutType::WITNESS_V0_KEYHASH && ctx != ParseScriptContext::P2WSH) {
uint160 hash(data[0]);
CKeyID keyid(hash);
CPubKey pubkey;
@@ -1009,7 +1009,7 @@ std::unique_ptr<DescriptorImpl> InferScript(const CScript& script, ParseScriptCo
return MakeUnique<WPKHDescriptor>(InferPubkey(pubkey, ctx, provider));
}
}
- if (txntype == TX_MULTISIG) {
+ if (txntype == TxoutType::MULTISIG) {
std::vector<std::unique_ptr<PubkeyProvider>> providers;
for (size_t i = 1; i + 1 < data.size(); ++i) {
CPubKey pubkey(data[i].begin(), data[i].end());
@@ -1017,7 +1017,7 @@ std::unique_ptr<DescriptorImpl> InferScript(const CScript& script, ParseScriptCo
}
return MakeUnique<MultisigDescriptor>((int)data[0][0], std::move(providers));
}
- if (txntype == TX_SCRIPTHASH && ctx == ParseScriptContext::TOP) {
+ if (txntype == TxoutType::SCRIPTHASH && ctx == ParseScriptContext::TOP) {
uint160 hash(data[0]);
CScriptID scriptid(hash);
CScript subscript;
@@ -1026,7 +1026,7 @@ std::unique_ptr<DescriptorImpl> InferScript(const CScript& script, ParseScriptCo
if (sub) return MakeUnique<SHDescriptor>(std::move(sub));
}
}
- if (txntype == TX_WITNESS_V0_SCRIPTHASH && ctx != ParseScriptContext::P2WSH) {
+ if (txntype == TxoutType::WITNESS_V0_SCRIPTHASH && ctx != ParseScriptContext::P2WSH) {
CScriptID scriptid;
CRIPEMD160().Write(data[0].data(), data[0].size()).Finalize(scriptid.begin());
CScript subscript;
diff --git a/src/script/sign.cpp b/src/script/sign.cpp
index 1e00afcf89..f425215549 100644
--- a/src/script/sign.cpp
+++ b/src/script/sign.cpp
@@ -92,11 +92,11 @@ static bool CreateSig(const BaseSignatureCreator& creator, SignatureData& sigdat
/**
* Sign scriptPubKey using signature made with creator.
* Signatures are returned in scriptSigRet (or returns false if scriptPubKey can't be signed),
- * unless whichTypeRet is TX_SCRIPTHASH, in which case scriptSigRet is the redemption script.
+ * unless whichTypeRet is TxoutType::SCRIPTHASH, in which case scriptSigRet is the redemption script.
* Returns false if scriptPubKey could not be completely satisfied.
*/
static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator& creator, const CScript& scriptPubKey,
- std::vector<valtype>& ret, txnouttype& whichTypeRet, SigVersion sigversion, SignatureData& sigdata)
+ std::vector<valtype>& ret, TxoutType& whichTypeRet, SigVersion sigversion, SignatureData& sigdata)
{
CScript scriptRet;
uint160 h160;
@@ -108,15 +108,15 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
switch (whichTypeRet)
{
- case TX_NONSTANDARD:
- case TX_NULL_DATA:
- case TX_WITNESS_UNKNOWN:
+ case TxoutType::NONSTANDARD:
+ case TxoutType::NULL_DATA:
+ case TxoutType::WITNESS_UNKNOWN:
return false;
- case TX_PUBKEY:
+ case TxoutType::PUBKEY:
if (!CreateSig(creator, sigdata, provider, sig, CPubKey(vSolutions[0]), scriptPubKey, sigversion)) return false;
ret.push_back(std::move(sig));
return true;
- case TX_PUBKEYHASH: {
+ case TxoutType::PUBKEYHASH: {
CKeyID keyID = CKeyID(uint160(vSolutions[0]));
CPubKey pubkey;
if (!GetPubKey(provider, sigdata, keyID, pubkey)) {
@@ -129,9 +129,9 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
ret.push_back(ToByteVector(pubkey));
return true;
}
- case TX_SCRIPTHASH:
+ case TxoutType::SCRIPTHASH:
h160 = uint160(vSolutions[0]);
- if (GetCScript(provider, sigdata, h160, scriptRet)) {
+ if (GetCScript(provider, sigdata, CScriptID{h160}, scriptRet)) {
ret.push_back(std::vector<unsigned char>(scriptRet.begin(), scriptRet.end()));
return true;
}
@@ -139,7 +139,7 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
sigdata.missing_redeem_script = h160;
return false;
- case TX_MULTISIG: {
+ case TxoutType::MULTISIG: {
size_t required = vSolutions.front()[0];
ret.push_back(valtype()); // workaround CHECKMULTISIG bug
for (size_t i = 1; i < vSolutions.size() - 1; ++i) {
@@ -159,13 +159,13 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
}
return ok;
}
- case TX_WITNESS_V0_KEYHASH:
+ case TxoutType::WITNESS_V0_KEYHASH:
ret.push_back(vSolutions[0]);
return true;
- case TX_WITNESS_V0_SCRIPTHASH:
+ case TxoutType::WITNESS_V0_SCRIPTHASH:
CRIPEMD160().Write(&vSolutions[0][0], vSolutions[0].size()).Finalize(h160.begin());
- if (GetCScript(provider, sigdata, h160, scriptRet)) {
+ if (GetCScript(provider, sigdata, CScriptID{h160}, scriptRet)) {
ret.push_back(std::vector<unsigned char>(scriptRet.begin(), scriptRet.end()));
return true;
}
@@ -198,44 +198,44 @@ bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreato
if (sigdata.complete) return true;
std::vector<valtype> result;
- txnouttype whichType;
+ TxoutType whichType;
bool solved = SignStep(provider, creator, fromPubKey, result, whichType, SigVersion::BASE, sigdata);
bool P2SH = false;
CScript subscript;
sigdata.scriptWitness.stack.clear();
- if (solved && whichType == TX_SCRIPTHASH)
+ if (solved && whichType == TxoutType::SCRIPTHASH)
{
// Solver returns the subscript that needs to be evaluated;
// the final scriptSig is the signatures from that
// and then the serialized subscript:
subscript = CScript(result[0].begin(), result[0].end());
sigdata.redeem_script = subscript;
- solved = solved && SignStep(provider, creator, subscript, result, whichType, SigVersion::BASE, sigdata) && whichType != TX_SCRIPTHASH;
+ solved = solved && SignStep(provider, creator, subscript, result, whichType, SigVersion::BASE, sigdata) && whichType != TxoutType::SCRIPTHASH;
P2SH = true;
}
- if (solved && whichType == TX_WITNESS_V0_KEYHASH)
+ if (solved && whichType == TxoutType::WITNESS_V0_KEYHASH)
{
CScript witnessscript;
witnessscript << OP_DUP << OP_HASH160 << ToByteVector(result[0]) << OP_EQUALVERIFY << OP_CHECKSIG;
- txnouttype subType;
+ TxoutType subType;
solved = solved && SignStep(provider, creator, witnessscript, result, subType, SigVersion::WITNESS_V0, sigdata);
sigdata.scriptWitness.stack = result;
sigdata.witness = true;
result.clear();
}
- else if (solved && whichType == TX_WITNESS_V0_SCRIPTHASH)
+ else if (solved && whichType == TxoutType::WITNESS_V0_SCRIPTHASH)
{
CScript witnessscript(result[0].begin(), result[0].end());
sigdata.witness_script = witnessscript;
- txnouttype subType;
- solved = solved && SignStep(provider, creator, witnessscript, result, subType, SigVersion::WITNESS_V0, sigdata) && subType != TX_SCRIPTHASH && subType != TX_WITNESS_V0_SCRIPTHASH && subType != TX_WITNESS_V0_KEYHASH;
+ TxoutType subType;
+ solved = solved && SignStep(provider, creator, witnessscript, result, subType, SigVersion::WITNESS_V0, sigdata) && subType != TxoutType::SCRIPTHASH && subType != TxoutType::WITNESS_V0_SCRIPTHASH && subType != TxoutType::WITNESS_V0_KEYHASH;
result.push_back(std::vector<unsigned char>(witnessscript.begin(), witnessscript.end()));
sigdata.scriptWitness.stack = result;
sigdata.witness = true;
result.clear();
- } else if (solved && whichType == TX_WITNESS_UNKNOWN) {
+ } else if (solved && whichType == TxoutType::WITNESS_UNKNOWN) {
sigdata.witness = true;
}
@@ -301,11 +301,11 @@ SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nI
// Get scripts
std::vector<std::vector<unsigned char>> solutions;
- txnouttype script_type = Solver(txout.scriptPubKey, solutions);
+ TxoutType script_type = Solver(txout.scriptPubKey, solutions);
SigVersion sigversion = SigVersion::BASE;
CScript next_script = txout.scriptPubKey;
- if (script_type == TX_SCRIPTHASH && !stack.script.empty() && !stack.script.back().empty()) {
+ if (script_type == TxoutType::SCRIPTHASH && !stack.script.empty() && !stack.script.back().empty()) {
// Get the redeemScript
CScript redeem_script(stack.script.back().begin(), stack.script.back().end());
data.redeem_script = redeem_script;
@@ -315,7 +315,7 @@ SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nI
script_type = Solver(next_script, solutions);
stack.script.pop_back();
}
- if (script_type == TX_WITNESS_V0_SCRIPTHASH && !stack.witness.empty() && !stack.witness.back().empty()) {
+ if (script_type == TxoutType::WITNESS_V0_SCRIPTHASH && !stack.witness.empty() && !stack.witness.back().empty()) {
// Get the witnessScript
CScript witness_script(stack.witness.back().begin(), stack.witness.back().end());
data.witness_script = witness_script;
@@ -328,7 +328,7 @@ SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nI
stack.witness.clear();
sigversion = SigVersion::WITNESS_V0;
}
- if (script_type == TX_MULTISIG && !stack.script.empty()) {
+ if (script_type == TxoutType::MULTISIG && !stack.script.empty()) {
// Build a map of pubkey -> signature by matching sigs to pubkeys:
assert(solutions.size() > 1);
unsigned int num_pubkeys = solutions.size()-2;
@@ -454,13 +454,13 @@ bool IsSegWitOutput(const SigningProvider& provider, const CScript& script)
{
std::vector<valtype> solutions;
auto whichtype = Solver(script, solutions);
- if (whichtype == TX_WITNESS_V0_SCRIPTHASH || whichtype == TX_WITNESS_V0_KEYHASH || whichtype == TX_WITNESS_UNKNOWN) return true;
- if (whichtype == TX_SCRIPTHASH) {
+ if (whichtype == TxoutType::WITNESS_V0_SCRIPTHASH || whichtype == TxoutType::WITNESS_V0_KEYHASH || whichtype == TxoutType::WITNESS_UNKNOWN) return true;
+ if (whichtype == TxoutType::SCRIPTHASH) {
auto h160 = uint160(solutions[0]);
CScript subscript;
- if (provider.GetCScript(h160, subscript)) {
+ if (provider.GetCScript(CScriptID{h160}, subscript)) {
whichtype = Solver(subscript, solutions);
- if (whichtype == TX_WITNESS_V0_SCRIPTHASH || whichtype == TX_WITNESS_V0_KEYHASH || whichtype == TX_WITNESS_UNKNOWN) return true;
+ if (whichtype == TxoutType::WITNESS_V0_SCRIPTHASH || whichtype == TxoutType::WITNESS_V0_KEYHASH || whichtype == TxoutType::WITNESS_UNKNOWN) return true;
}
}
return false;
diff --git a/src/script/signingprovider.cpp b/src/script/signingprovider.cpp
index 01757e2f65..2d8dc7d471 100644
--- a/src/script/signingprovider.cpp
+++ b/src/script/signingprovider.cpp
@@ -180,10 +180,10 @@ CKeyID GetKeyForDestination(const SigningProvider& store, const CTxDestination&
// Only supports destinations which map to single public keys, i.e. P2PKH,
// P2WPKH, and P2SH-P2WPKH.
if (auto id = boost::get<PKHash>(&dest)) {
- return CKeyID(*id);
+ return ToKeyID(*id);
}
if (auto witness_id = boost::get<WitnessV0KeyHash>(&dest)) {
- return CKeyID(*witness_id);
+ return ToKeyID(*witness_id);
}
if (auto script_hash = boost::get<ScriptHash>(&dest)) {
CScript script;
@@ -191,7 +191,7 @@ CKeyID GetKeyForDestination(const SigningProvider& store, const CTxDestination&
CTxDestination inner_dest;
if (store.GetCScript(script_id, script) && ExtractDestination(script, inner_dest)) {
if (auto inner_witness_id = boost::get<WitnessV0KeyHash>(&inner_dest)) {
- return CKeyID(*inner_witness_id);
+ return ToKeyID(*inner_witness_id);
}
}
}
diff --git a/src/script/standard.cpp b/src/script/standard.cpp
index defdfa8d74..251be8d271 100644
--- a/src/script/standard.cpp
+++ b/src/script/standard.cpp
@@ -16,31 +16,47 @@ typedef std::vector<unsigned char> valtype;
bool fAcceptDatacarrier = DEFAULT_ACCEPT_DATACARRIER;
unsigned nMaxDatacarrierBytes = MAX_OP_RETURN_RELAY;
-CScriptID::CScriptID(const CScript& in) : uint160(Hash160(in.begin(), in.end())) {}
+CScriptID::CScriptID(const CScript& in) : BaseHash(Hash160(in.begin(), in.end())) {}
+CScriptID::CScriptID(const ScriptHash& in) : BaseHash(static_cast<uint160>(in)) {}
-ScriptHash::ScriptHash(const CScript& in) : uint160(Hash160(in.begin(), in.end())) {}
+ScriptHash::ScriptHash(const CScript& in) : BaseHash(Hash160(in.begin(), in.end())) {}
+ScriptHash::ScriptHash(const CScriptID& in) : BaseHash(static_cast<uint160>(in)) {}
-PKHash::PKHash(const CPubKey& pubkey) : uint160(pubkey.GetID()) {}
+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)};
+}
WitnessV0ScriptHash::WitnessV0ScriptHash(const CScript& in)
{
CSHA256().Write(in.data(), in.size()).Finalize(begin());
}
-std::string GetTxnOutputType(txnouttype t)
+std::string GetTxnOutputType(TxoutType t)
{
switch (t)
{
- case TX_NONSTANDARD: return "nonstandard";
- case TX_PUBKEY: return "pubkey";
- case TX_PUBKEYHASH: return "pubkeyhash";
- case TX_SCRIPTHASH: return "scripthash";
- case TX_MULTISIG: return "multisig";
- case TX_NULL_DATA: return "nulldata";
- case TX_WITNESS_V0_KEYHASH: return "witness_v0_keyhash";
- case TX_WITNESS_V0_SCRIPTHASH: return "witness_v0_scripthash";
- case TX_WITNESS_UNKNOWN: return "witness_unknown";
- }
+ case TxoutType::NONSTANDARD: return "nonstandard";
+ case TxoutType::PUBKEY: return "pubkey";
+ case TxoutType::PUBKEYHASH: return "pubkeyhash";
+ case TxoutType::SCRIPTHASH: return "scripthash";
+ case TxoutType::MULTISIG: return "multisig";
+ case TxoutType::NULL_DATA: return "nulldata";
+ case TxoutType::WITNESS_V0_KEYHASH: return "witness_v0_keyhash";
+ case TxoutType::WITNESS_V0_SCRIPTHASH: return "witness_v0_scripthash";
+ case TxoutType::WITNESS_UNKNOWN: return "witness_unknown";
+ } // no default case, so the compiler can warn about missing cases
assert(false);
}
@@ -90,7 +106,7 @@ static bool MatchMultisig(const CScript& script, unsigned int& required, std::ve
return (it + 1 == script.end());
}
-txnouttype Solver(const CScript& scriptPubKey, std::vector<std::vector<unsigned char>>& vSolutionsRet)
+TxoutType Solver(const CScript& scriptPubKey, std::vector<std::vector<unsigned char>>& vSolutionsRet)
{
vSolutionsRet.clear();
@@ -100,7 +116,7 @@ txnouttype Solver(const CScript& scriptPubKey, std::vector<std::vector<unsigned
{
std::vector<unsigned char> hashBytes(scriptPubKey.begin()+2, scriptPubKey.begin()+22);
vSolutionsRet.push_back(hashBytes);
- return TX_SCRIPTHASH;
+ return TxoutType::SCRIPTHASH;
}
int witnessversion;
@@ -108,18 +124,18 @@ txnouttype Solver(const CScript& scriptPubKey, std::vector<std::vector<unsigned
if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
if (witnessversion == 0 && witnessprogram.size() == WITNESS_V0_KEYHASH_SIZE) {
vSolutionsRet.push_back(witnessprogram);
- return TX_WITNESS_V0_KEYHASH;
+ return TxoutType::WITNESS_V0_KEYHASH;
}
if (witnessversion == 0 && witnessprogram.size() == WITNESS_V0_SCRIPTHASH_SIZE) {
vSolutionsRet.push_back(witnessprogram);
- return TX_WITNESS_V0_SCRIPTHASH;
+ return TxoutType::WITNESS_V0_SCRIPTHASH;
}
if (witnessversion != 0) {
vSolutionsRet.push_back(std::vector<unsigned char>{(unsigned char)witnessversion});
vSolutionsRet.push_back(std::move(witnessprogram));
- return TX_WITNESS_UNKNOWN;
+ return TxoutType::WITNESS_UNKNOWN;
}
- return TX_NONSTANDARD;
+ return TxoutType::NONSTANDARD;
}
// Provably prunable, data-carrying output
@@ -128,18 +144,18 @@ txnouttype Solver(const CScript& scriptPubKey, std::vector<std::vector<unsigned
// byte passes the IsPushOnly() test we don't care what exactly is in the
// script.
if (scriptPubKey.size() >= 1 && scriptPubKey[0] == OP_RETURN && scriptPubKey.IsPushOnly(scriptPubKey.begin()+1)) {
- return TX_NULL_DATA;
+ return TxoutType::NULL_DATA;
}
std::vector<unsigned char> data;
if (MatchPayToPubkey(scriptPubKey, data)) {
vSolutionsRet.push_back(std::move(data));
- return TX_PUBKEY;
+ return TxoutType::PUBKEY;
}
if (MatchPayToPubkeyHash(scriptPubKey, data)) {
vSolutionsRet.push_back(std::move(data));
- return TX_PUBKEYHASH;
+ return TxoutType::PUBKEYHASH;
}
unsigned int required;
@@ -148,19 +164,19 @@ txnouttype Solver(const CScript& scriptPubKey, std::vector<std::vector<unsigned
vSolutionsRet.push_back({static_cast<unsigned char>(required)}); // safe as required is in range 1..16
vSolutionsRet.insert(vSolutionsRet.end(), keys.begin(), keys.end());
vSolutionsRet.push_back({static_cast<unsigned char>(keys.size())}); // safe as size is in range 1..16
- return TX_MULTISIG;
+ return TxoutType::MULTISIG;
}
vSolutionsRet.clear();
- return TX_NONSTANDARD;
+ return TxoutType::NONSTANDARD;
}
bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
{
std::vector<valtype> vSolutions;
- txnouttype whichType = Solver(scriptPubKey, vSolutions);
+ TxoutType whichType = Solver(scriptPubKey, vSolutions);
- if (whichType == TX_PUBKEY) {
+ if (whichType == TxoutType::PUBKEY) {
CPubKey pubKey(vSolutions[0]);
if (!pubKey.IsValid())
return false;
@@ -168,26 +184,26 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
addressRet = PKHash(pubKey);
return true;
}
- else if (whichType == TX_PUBKEYHASH)
+ else if (whichType == TxoutType::PUBKEYHASH)
{
addressRet = PKHash(uint160(vSolutions[0]));
return true;
}
- else if (whichType == TX_SCRIPTHASH)
+ else if (whichType == TxoutType::SCRIPTHASH)
{
addressRet = ScriptHash(uint160(vSolutions[0]));
return true;
- } else if (whichType == TX_WITNESS_V0_KEYHASH) {
+ } else if (whichType == TxoutType::WITNESS_V0_KEYHASH) {
WitnessV0KeyHash hash;
std::copy(vSolutions[0].begin(), vSolutions[0].end(), hash.begin());
addressRet = hash;
return true;
- } else if (whichType == TX_WITNESS_V0_SCRIPTHASH) {
+ } else if (whichType == TxoutType::WITNESS_V0_SCRIPTHASH) {
WitnessV0ScriptHash hash;
std::copy(vSolutions[0].begin(), vSolutions[0].end(), hash.begin());
addressRet = hash;
return true;
- } else if (whichType == TX_WITNESS_UNKNOWN) {
+ } else if (whichType == TxoutType::WITNESS_UNKNOWN) {
WitnessUnknown unk;
unk.version = vSolutions[0][0];
std::copy(vSolutions[1].begin(), vSolutions[1].end(), unk.program);
@@ -199,19 +215,19 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
return false;
}
-bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet)
+bool ExtractDestinations(const CScript& scriptPubKey, TxoutType& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet)
{
addressRet.clear();
std::vector<valtype> vSolutions;
typeRet = Solver(scriptPubKey, vSolutions);
- if (typeRet == TX_NONSTANDARD) {
+ if (typeRet == TxoutType::NONSTANDARD) {
return false;
- } else if (typeRet == TX_NULL_DATA) {
+ } else if (typeRet == TxoutType::NULL_DATA) {
// This is data, not addresses
return false;
}
- if (typeRet == TX_MULTISIG)
+ if (typeRet == TxoutType::MULTISIG)
{
nRequiredRet = vSolutions.front()[0];
for (unsigned int i = 1; i < vSolutions.size()-1; i++)
@@ -300,11 +316,11 @@ CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys)
CScript GetScriptForWitness(const CScript& redeemscript)
{
std::vector<std::vector<unsigned char> > vSolutions;
- txnouttype typ = Solver(redeemscript, vSolutions);
- if (typ == TX_PUBKEY) {
+ TxoutType typ = Solver(redeemscript, vSolutions);
+ if (typ == TxoutType::PUBKEY) {
return GetScriptForDestination(WitnessV0KeyHash(Hash160(vSolutions[0].begin(), vSolutions[0].end())));
- } else if (typ == TX_PUBKEYHASH) {
- return GetScriptForDestination(WitnessV0KeyHash(vSolutions[0]));
+ } else if (typ == TxoutType::PUBKEYHASH) {
+ return GetScriptForDestination(WitnessV0KeyHash(uint160{vSolutions[0]}));
}
return GetScriptForDestination(WitnessV0ScriptHash(redeemscript));
}
diff --git a/src/script/standard.h b/src/script/standard.h
index 2929425670..fd29353886 100644
--- a/src/script/standard.h
+++ b/src/script/standard.h
@@ -18,14 +18,77 @@ static const bool DEFAULT_ACCEPT_DATACARRIER = true;
class CKeyID;
class CScript;
+struct ScriptHash;
+
+template<typename HashType>
+class BaseHash
+{
+protected:
+ HashType m_hash;
+
+public:
+ BaseHash() : m_hash() {}
+ BaseHash(const HashType& in) : m_hash(in) {}
+
+ unsigned char* begin()
+ {
+ return m_hash.begin();
+ }
+
+ const unsigned char* begin() const
+ {
+ return m_hash.begin();
+ }
+
+ unsigned char* end()
+ {
+ return m_hash.end();
+ }
+
+ const unsigned char* end() const
+ {
+ return m_hash.end();
+ }
+
+ operator std::vector<unsigned char>() const
+ {
+ return std::vector<unsigned char>{m_hash.begin(), m_hash.end()};
+ }
+
+ std::string ToString() const
+ {
+ return m_hash.ToString();
+ }
+
+ bool operator==(const BaseHash<HashType>& other) const noexcept
+ {
+ return m_hash == other.m_hash;
+ }
+
+ bool operator!=(const BaseHash<HashType>& other) const noexcept
+ {
+ return !(m_hash == other.m_hash);
+ }
+
+ bool operator<(const BaseHash<HashType>& other) const noexcept
+ {
+ return m_hash < other.m_hash;
+ }
+
+ size_t size() const
+ {
+ return m_hash.size();
+ }
+};
/** A reference to a CScript: the Hash160 of its serialization (see script.h) */
-class CScriptID : public uint160
+class CScriptID : public BaseHash<uint160>
{
public:
- CScriptID() : uint160() {}
+ CScriptID() : BaseHash() {}
explicit CScriptID(const CScript& in);
- CScriptID(const uint160& in) : uint160(in) {}
+ explicit CScriptID(const uint160& in) : BaseHash(in) {}
+ explicit CScriptID(const ScriptHash& in);
};
/**
@@ -36,11 +99,11 @@ static const unsigned int MAX_OP_RETURN_RELAY = 83;
/**
* A data carrying output is an unspendable output containing data. The script
- * type is designated as TX_NULL_DATA.
+ * type is designated as TxoutType::NULL_DATA.
*/
extern bool fAcceptDatacarrier;
-/** Maximum size of TX_NULL_DATA scripts that this node considers standard. */
+/** Maximum size of TxoutType::NULL_DATA scripts that this node considers standard. */
extern unsigned nMaxDatacarrierBytes;
/**
@@ -53,18 +116,17 @@ extern unsigned nMaxDatacarrierBytes;
*/
static const unsigned int MANDATORY_SCRIPT_VERIFY_FLAGS = SCRIPT_VERIFY_P2SH;
-enum txnouttype
-{
- TX_NONSTANDARD,
+enum class TxoutType {
+ NONSTANDARD,
// 'standard' transaction types:
- TX_PUBKEY,
- TX_PUBKEYHASH,
- TX_SCRIPTHASH,
- TX_MULTISIG,
- TX_NULL_DATA, //!< unspendable OP_RETURN script that carries data
- TX_WITNESS_V0_SCRIPTHASH,
- TX_WITNESS_V0_KEYHASH,
- TX_WITNESS_UNKNOWN, //!< Only for Witness versions not already defined above
+ PUBKEY,
+ PUBKEYHASH,
+ SCRIPTHASH,
+ MULTISIG,
+ NULL_DATA, //!< unspendable OP_RETURN script that carries data
+ WITNESS_V0_SCRIPTHASH,
+ WITNESS_V0_KEYHASH,
+ WITNESS_UNKNOWN, //!< Only for Witness versions not already defined above
};
class CNoDestination {
@@ -73,41 +135,44 @@ public:
friend bool operator<(const CNoDestination &a, const CNoDestination &b) { return true; }
};
-struct PKHash : public uint160
+struct PKHash : public BaseHash<uint160>
{
- PKHash() : uint160() {}
- explicit PKHash(const uint160& hash) : uint160(hash) {}
+ PKHash() : BaseHash() {}
+ explicit PKHash(const uint160& hash) : BaseHash(hash) {}
explicit PKHash(const CPubKey& pubkey);
- using uint160::uint160;
+ explicit PKHash(const CKeyID& pubkey_id);
};
+CKeyID ToKeyID(const PKHash& key_hash);
struct WitnessV0KeyHash;
-struct ScriptHash : public uint160
+struct ScriptHash : public BaseHash<uint160>
{
- ScriptHash() : uint160() {}
+ ScriptHash() : BaseHash() {}
// These don't do what you'd expect.
// Use ScriptHash(GetScriptForDestination(...)) instead.
explicit ScriptHash(const WitnessV0KeyHash& hash) = delete;
explicit ScriptHash(const PKHash& hash) = delete;
- explicit ScriptHash(const uint160& hash) : uint160(hash) {}
+
+ explicit ScriptHash(const uint160& hash) : BaseHash(hash) {}
explicit ScriptHash(const CScript& script);
- using uint160::uint160;
+ explicit ScriptHash(const CScriptID& script);
};
-struct WitnessV0ScriptHash : public uint256
+struct WitnessV0ScriptHash : public BaseHash<uint256>
{
- WitnessV0ScriptHash() : uint256() {}
- explicit WitnessV0ScriptHash(const uint256& hash) : uint256(hash) {}
+ WitnessV0ScriptHash() : BaseHash() {}
+ explicit WitnessV0ScriptHash(const uint256& hash) : BaseHash(hash) {}
explicit WitnessV0ScriptHash(const CScript& script);
- using uint256::uint256;
};
-struct WitnessV0KeyHash : public uint160
+struct WitnessV0KeyHash : public BaseHash<uint160>
{
- WitnessV0KeyHash() : uint160() {}
- explicit WitnessV0KeyHash(const uint160& hash) : uint160(hash) {}
- using uint160::uint160;
+ WitnessV0KeyHash() : BaseHash() {}
+ explicit WitnessV0KeyHash(const uint160& hash) : BaseHash(hash) {}
+ explicit WitnessV0KeyHash(const CPubKey& pubkey);
+ explicit WitnessV0KeyHash(const PKHash& pubkey_hash);
};
+CKeyID ToKeyID(const WitnessV0KeyHash& key_hash);
//! CTxDestination subtype to encode any future Witness version
struct WitnessUnknown
@@ -134,11 +199,11 @@ struct WitnessUnknown
/**
* A txout script template with a specific destination. It is either:
* * CNoDestination: no destination set
- * * PKHash: TX_PUBKEYHASH destination (P2PKH)
- * * ScriptHash: TX_SCRIPTHASH destination (P2SH)
- * * WitnessV0ScriptHash: TX_WITNESS_V0_SCRIPTHASH destination (P2WSH)
- * * WitnessV0KeyHash: TX_WITNESS_V0_KEYHASH destination (P2WPKH)
- * * WitnessUnknown: TX_WITNESS_UNKNOWN destination (P2W???)
+ * * PKHash: TxoutType::PUBKEYHASH destination (P2PKH)
+ * * ScriptHash: TxoutType::SCRIPTHASH destination (P2SH)
+ * * WitnessV0ScriptHash: TxoutType::WITNESS_V0_SCRIPTHASH destination (P2WSH)
+ * * WitnessV0KeyHash: TxoutType::WITNESS_V0_KEYHASH destination (P2WPKH)
+ * * WitnessUnknown: TxoutType::WITNESS_UNKNOWN destination (P2W???)
* A CTxDestination is the internal data type encoded in a bitcoin address
*/
typedef boost::variant<CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessUnknown> CTxDestination;
@@ -146,8 +211,8 @@ typedef boost::variant<CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash,
/** Check whether a CTxDestination is a CNoDestination. */
bool IsValidDestination(const CTxDestination& dest);
-/** Get the name of a txnouttype as a C string, or nullptr if unknown. */
-std::string GetTxnOutputType(txnouttype t);
+/** Get the name of a TxoutType as a string */
+std::string GetTxnOutputType(TxoutType t);
/**
* Parse a scriptPubKey and identify script type for standard scripts. If
@@ -157,9 +222,9 @@ std::string GetTxnOutputType(txnouttype t);
*
* @param[in] scriptPubKey Script to parse
* @param[out] vSolutionsRet Vector of parsed pubkeys and hashes
- * @return The script type. TX_NONSTANDARD represents a failed solve.
+ * @return The script type. TxoutType::NONSTANDARD represents a failed solve.
*/
-txnouttype Solver(const CScript& scriptPubKey, std::vector<std::vector<unsigned char>>& vSolutionsRet);
+TxoutType Solver(const CScript& scriptPubKey, std::vector<std::vector<unsigned char>>& vSolutionsRet);
/**
* Parse a standard scriptPubKey for the destination address. Assigns result to
@@ -180,7 +245,7 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
* encodable as an address) with key identifiers (of keys involved in a
* CScript), and its use should be phased out.
*/
-bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet);
+bool ExtractDestinations(const CScript& scriptPubKey, TxoutType& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet);
/**
* Generate a Bitcoin scriptPubKey for the given CTxDestination. Returns a P2PKH