mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-04-29 14:59:39 -04:00
scripted-diff: TxoutType C++11 scoped enum class
-BEGIN VERIFY SCRIPT- # General rename helper: $1 -> $2 rename_global() { sed -i "s/\<$1\>/$2/g" $(git grep -l "$1"); } # Helper to rename TxoutType $1 rename_value() { sed -i "s/ TX_$1,/ $1,/g" src/script/standard.h; # First strip the prefix in the definition (header) rename_global TX_$1 "TxoutType::$1"; # Then replace globally } # Change the type globally to bring it in line with the style-guide # (clsses are UpperCamelCase) rename_global 'enum txnouttype' 'enum class TxoutType' rename_global 'txnouttype' 'TxoutType' # Now rename each enum value rename_value 'NONSTANDARD' rename_value 'PUBKEY' rename_value 'PUBKEYHASH' rename_value 'SCRIPTHASH' rename_value 'MULTISIG' rename_value 'NULL_DATA' rename_value 'WITNESS_V0_KEYHASH' rename_value 'WITNESS_V0_SCRIPTHASH' rename_value 'WITNESS_UNKNOWN' -END VERIFY SCRIPT-
This commit is contained in:
parent
fa95a694c4
commit
fa32adf9dc
18 changed files with 208 additions and 208 deletions
|
@ -135,8 +135,8 @@ bool CBloomFilter::IsRelevantAndUpdate(const CTransaction& tx)
|
||||||
else if ((nFlags & BLOOM_UPDATE_MASK) == BLOOM_UPDATE_P2PUBKEY_ONLY)
|
else if ((nFlags & BLOOM_UPDATE_MASK) == BLOOM_UPDATE_P2PUBKEY_ONLY)
|
||||||
{
|
{
|
||||||
std::vector<std::vector<unsigned char> > vSolutions;
|
std::vector<std::vector<unsigned char> > vSolutions;
|
||||||
txnouttype type = Solver(txout.scriptPubKey, vSolutions);
|
TxoutType type = Solver(txout.scriptPubKey, vSolutions);
|
||||||
if (type == TX_PUBKEY || type == TX_MULTISIG) {
|
if (type == TxoutType::PUBKEY || type == TxoutType::MULTISIG) {
|
||||||
insert(COutPoint(hash, i));
|
insert(COutPoint(hash, i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,11 +140,11 @@ void ScriptToUniv(const CScript& script, UniValue& out, bool include_address)
|
||||||
out.pushKV("hex", HexStr(script.begin(), script.end()));
|
out.pushKV("hex", HexStr(script.begin(), script.end()));
|
||||||
|
|
||||||
std::vector<std::vector<unsigned char>> solns;
|
std::vector<std::vector<unsigned char>> solns;
|
||||||
txnouttype type = Solver(script, solns);
|
TxoutType type = Solver(script, solns);
|
||||||
out.pushKV("type", GetTxnOutputType(type));
|
out.pushKV("type", GetTxnOutputType(type));
|
||||||
|
|
||||||
CTxDestination address;
|
CTxDestination address;
|
||||||
if (include_address && ExtractDestination(script, address) && type != TX_PUBKEY) {
|
if (include_address && ExtractDestination(script, address) && type != TxoutType::PUBKEY) {
|
||||||
out.pushKV("address", EncodeDestination(address));
|
out.pushKV("address", EncodeDestination(address));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,7 +152,7 @@ void ScriptToUniv(const CScript& script, UniValue& out, bool include_address)
|
||||||
void ScriptPubKeyToUniv(const CScript& scriptPubKey,
|
void ScriptPubKeyToUniv(const CScript& scriptPubKey,
|
||||||
UniValue& out, bool fIncludeHex)
|
UniValue& out, bool fIncludeHex)
|
||||||
{
|
{
|
||||||
txnouttype type;
|
TxoutType type;
|
||||||
std::vector<CTxDestination> addresses;
|
std::vector<CTxDestination> addresses;
|
||||||
int nRequired;
|
int nRequired;
|
||||||
|
|
||||||
|
@ -160,7 +160,7 @@ void ScriptPubKeyToUniv(const CScript& scriptPubKey,
|
||||||
if (fIncludeHex)
|
if (fIncludeHex)
|
||||||
out.pushKV("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end()));
|
out.pushKV("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end()));
|
||||||
|
|
||||||
if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired) || type == TX_PUBKEY) {
|
if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired) || type == TxoutType::PUBKEY) {
|
||||||
out.pushKV("type", GetTxnOutputType(type));
|
out.pushKV("type", GetTxnOutputType(type));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,14 +50,14 @@ bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
|
||||||
return (txout.nValue < GetDustThreshold(txout, dustRelayFeeIn));
|
return (txout.nValue < GetDustThreshold(txout, dustRelayFeeIn));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType)
|
bool IsStandard(const CScript& scriptPubKey, TxoutType& whichType)
|
||||||
{
|
{
|
||||||
std::vector<std::vector<unsigned char> > vSolutions;
|
std::vector<std::vector<unsigned char> > vSolutions;
|
||||||
whichType = Solver(scriptPubKey, vSolutions);
|
whichType = Solver(scriptPubKey, vSolutions);
|
||||||
|
|
||||||
if (whichType == TX_NONSTANDARD) {
|
if (whichType == TxoutType::NONSTANDARD) {
|
||||||
return false;
|
return false;
|
||||||
} else if (whichType == TX_MULTISIG) {
|
} else if (whichType == TxoutType::MULTISIG) {
|
||||||
unsigned char m = vSolutions.front()[0];
|
unsigned char m = vSolutions.front()[0];
|
||||||
unsigned char n = vSolutions.back()[0];
|
unsigned char n = vSolutions.back()[0];
|
||||||
// Support up to x-of-3 multisig txns as standard
|
// Support up to x-of-3 multisig txns as standard
|
||||||
|
@ -65,7 +65,7 @@ bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType)
|
||||||
return false;
|
return false;
|
||||||
if (m < 1 || m > n)
|
if (m < 1 || m > n)
|
||||||
return false;
|
return false;
|
||||||
} else if (whichType == TX_NULL_DATA &&
|
} else if (whichType == TxoutType::NULL_DATA &&
|
||||||
(!fAcceptDatacarrier || scriptPubKey.size() > nMaxDatacarrierBytes)) {
|
(!fAcceptDatacarrier || scriptPubKey.size() > nMaxDatacarrierBytes)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -110,16 +110,16 @@ bool IsStandardTx(const CTransaction& tx, bool permit_bare_multisig, const CFeeR
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int nDataOut = 0;
|
unsigned int nDataOut = 0;
|
||||||
txnouttype whichType;
|
TxoutType whichType;
|
||||||
for (const CTxOut& txout : tx.vout) {
|
for (const CTxOut& txout : tx.vout) {
|
||||||
if (!::IsStandard(txout.scriptPubKey, whichType)) {
|
if (!::IsStandard(txout.scriptPubKey, whichType)) {
|
||||||
reason = "scriptpubkey";
|
reason = "scriptpubkey";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (whichType == TX_NULL_DATA)
|
if (whichType == TxoutType::NULL_DATA)
|
||||||
nDataOut++;
|
nDataOut++;
|
||||||
else if ((whichType == TX_MULTISIG) && (!permit_bare_multisig)) {
|
else if ((whichType == TxoutType::MULTISIG) && (!permit_bare_multisig)) {
|
||||||
reason = "bare-multisig";
|
reason = "bare-multisig";
|
||||||
return false;
|
return false;
|
||||||
} else if (IsDust(txout, dust_relay_fee)) {
|
} else if (IsDust(txout, dust_relay_fee)) {
|
||||||
|
@ -163,10 +163,10 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
|
||||||
const CTxOut& prev = mapInputs.AccessCoin(tx.vin[i].prevout).out;
|
const CTxOut& prev = mapInputs.AccessCoin(tx.vin[i].prevout).out;
|
||||||
|
|
||||||
std::vector<std::vector<unsigned char> > vSolutions;
|
std::vector<std::vector<unsigned char> > vSolutions;
|
||||||
txnouttype whichType = Solver(prev.scriptPubKey, vSolutions);
|
TxoutType whichType = Solver(prev.scriptPubKey, vSolutions);
|
||||||
if (whichType == TX_NONSTANDARD) {
|
if (whichType == TxoutType::NONSTANDARD) {
|
||||||
return false;
|
return false;
|
||||||
} else if (whichType == TX_SCRIPTHASH) {
|
} else if (whichType == TxoutType::SCRIPTHASH) {
|
||||||
std::vector<std::vector<unsigned char> > stack;
|
std::vector<std::vector<unsigned char> > stack;
|
||||||
// convert the scriptSig into a stack, so we can inspect the redeemScript
|
// convert the scriptSig into a stack, so we can inspect the redeemScript
|
||||||
if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), SigVersion::BASE))
|
if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), SigVersion::BASE))
|
||||||
|
|
|
@ -81,7 +81,7 @@ CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFee);
|
||||||
|
|
||||||
bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFee);
|
bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFee);
|
||||||
|
|
||||||
bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType);
|
bool IsStandard(const CScript& scriptPubKey, TxoutType& whichType);
|
||||||
/**
|
/**
|
||||||
* Check for standard transaction types
|
* Check for standard transaction types
|
||||||
* @return True if all outputs (scriptPubKeys) use only standard transaction forms
|
* @return True if all outputs (scriptPubKeys) use only standard transaction forms
|
||||||
|
|
|
@ -512,9 +512,9 @@ static UniValue decoderawtransaction(const JSONRPCRequest& request)
|
||||||
static std::string GetAllOutputTypes()
|
static std::string GetAllOutputTypes()
|
||||||
{
|
{
|
||||||
std::vector<std::string> ret;
|
std::vector<std::string> ret;
|
||||||
using U = std::underlying_type<txnouttype>::type;
|
using U = std::underlying_type<TxoutType>::type;
|
||||||
for (U i = (U)TX_NONSTANDARD; i <= (U)TX_WITNESS_UNKNOWN; ++i) {
|
for (U i = (U)TxoutType::NONSTANDARD; i <= (U)TxoutType::WITNESS_UNKNOWN; ++i) {
|
||||||
ret.emplace_back(GetTxnOutputType(static_cast<txnouttype>(i)));
|
ret.emplace_back(GetTxnOutputType(static_cast<TxoutType>(i)));
|
||||||
}
|
}
|
||||||
return Join(ret, ", ");
|
return Join(ret, ", ");
|
||||||
}
|
}
|
||||||
|
@ -580,10 +580,10 @@ static UniValue decodescript(const JSONRPCRequest& request)
|
||||||
// is a witness program, don't return addresses for a segwit programs.
|
// is a witness program, don't return addresses for a segwit programs.
|
||||||
if (type.get_str() == "pubkey" || type.get_str() == "pubkeyhash" || type.get_str() == "multisig" || type.get_str() == "nonstandard") {
|
if (type.get_str() == "pubkey" || type.get_str() == "pubkeyhash" || type.get_str() == "multisig" || type.get_str() == "nonstandard") {
|
||||||
std::vector<std::vector<unsigned char>> solutions_data;
|
std::vector<std::vector<unsigned char>> solutions_data;
|
||||||
txnouttype which_type = Solver(script, solutions_data);
|
TxoutType which_type = Solver(script, solutions_data);
|
||||||
// Uncompressed pubkeys cannot be used with segwit checksigs.
|
// Uncompressed pubkeys cannot be used with segwit checksigs.
|
||||||
// If the script contains an uncompressed pubkey, skip encoding of a segwit program.
|
// If the script contains an uncompressed pubkey, skip encoding of a segwit program.
|
||||||
if ((which_type == TX_PUBKEY) || (which_type == TX_MULTISIG)) {
|
if ((which_type == TxoutType::PUBKEY) || (which_type == TxoutType::MULTISIG)) {
|
||||||
for (const auto& solution : solutions_data) {
|
for (const auto& solution : solutions_data) {
|
||||||
if ((solution.size() != 1) && !CPubKey(solution).IsCompressed()) {
|
if ((solution.size() != 1) && !CPubKey(solution).IsCompressed()) {
|
||||||
return r;
|
return r;
|
||||||
|
@ -592,9 +592,9 @@ static UniValue decodescript(const JSONRPCRequest& request)
|
||||||
}
|
}
|
||||||
UniValue sr(UniValue::VOBJ);
|
UniValue sr(UniValue::VOBJ);
|
||||||
CScript segwitScr;
|
CScript segwitScr;
|
||||||
if (which_type == TX_PUBKEY) {
|
if (which_type == TxoutType::PUBKEY) {
|
||||||
segwitScr = GetScriptForDestination(WitnessV0KeyHash(Hash160(solutions_data[0].begin(), solutions_data[0].end())));
|
segwitScr = GetScriptForDestination(WitnessV0KeyHash(Hash160(solutions_data[0].begin(), solutions_data[0].end())));
|
||||||
} else if (which_type == TX_PUBKEYHASH) {
|
} else if (which_type == TxoutType::PUBKEYHASH) {
|
||||||
segwitScr = GetScriptForDestination(WitnessV0KeyHash(uint160{solutions_data[0]}));
|
segwitScr = GetScriptForDestination(WitnessV0KeyHash(uint160{solutions_data[0]}));
|
||||||
} else {
|
} else {
|
||||||
// Scripts that are not fit for P2WPKH are encoded as P2WSH.
|
// Scripts that are not fit for P2WPKH are encoded as P2WSH.
|
||||||
|
|
|
@ -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::unique_ptr<DescriptorImpl> InferScript(const CScript& script, ParseScriptContext ctx, const SigningProvider& provider)
|
||||||
{
|
{
|
||||||
std::vector<std::vector<unsigned char>> data;
|
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());
|
CPubKey pubkey(data[0].begin(), data[0].end());
|
||||||
if (pubkey.IsValid()) {
|
if (pubkey.IsValid()) {
|
||||||
return MakeUnique<PKDescriptor>(InferPubkey(pubkey, ctx, provider));
|
return MakeUnique<PKDescriptor>(InferPubkey(pubkey, ctx, provider));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (txntype == TX_PUBKEYHASH) {
|
if (txntype == TxoutType::PUBKEYHASH) {
|
||||||
uint160 hash(data[0]);
|
uint160 hash(data[0]);
|
||||||
CKeyID keyid(hash);
|
CKeyID keyid(hash);
|
||||||
CPubKey pubkey;
|
CPubKey pubkey;
|
||||||
|
@ -1001,7 +1001,7 @@ std::unique_ptr<DescriptorImpl> InferScript(const CScript& script, ParseScriptCo
|
||||||
return MakeUnique<PKHDescriptor>(InferPubkey(pubkey, ctx, provider));
|
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]);
|
uint160 hash(data[0]);
|
||||||
CKeyID keyid(hash);
|
CKeyID keyid(hash);
|
||||||
CPubKey pubkey;
|
CPubKey pubkey;
|
||||||
|
@ -1009,7 +1009,7 @@ std::unique_ptr<DescriptorImpl> InferScript(const CScript& script, ParseScriptCo
|
||||||
return MakeUnique<WPKHDescriptor>(InferPubkey(pubkey, ctx, provider));
|
return MakeUnique<WPKHDescriptor>(InferPubkey(pubkey, ctx, provider));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (txntype == TX_MULTISIG) {
|
if (txntype == TxoutType::MULTISIG) {
|
||||||
std::vector<std::unique_ptr<PubkeyProvider>> providers;
|
std::vector<std::unique_ptr<PubkeyProvider>> providers;
|
||||||
for (size_t i = 1; i + 1 < data.size(); ++i) {
|
for (size_t i = 1; i + 1 < data.size(); ++i) {
|
||||||
CPubKey pubkey(data[i].begin(), data[i].end());
|
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));
|
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]);
|
uint160 hash(data[0]);
|
||||||
CScriptID scriptid(hash);
|
CScriptID scriptid(hash);
|
||||||
CScript subscript;
|
CScript subscript;
|
||||||
|
@ -1026,7 +1026,7 @@ std::unique_ptr<DescriptorImpl> InferScript(const CScript& script, ParseScriptCo
|
||||||
if (sub) return MakeUnique<SHDescriptor>(std::move(sub));
|
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;
|
CScriptID scriptid;
|
||||||
CRIPEMD160().Write(data[0].data(), data[0].size()).Finalize(scriptid.begin());
|
CRIPEMD160().Write(data[0].data(), data[0].size()).Finalize(scriptid.begin());
|
||||||
CScript subscript;
|
CScript subscript;
|
||||||
|
|
|
@ -92,11 +92,11 @@ static bool CreateSig(const BaseSignatureCreator& creator, SignatureData& sigdat
|
||||||
/**
|
/**
|
||||||
* Sign scriptPubKey using signature made with creator.
|
* Sign scriptPubKey using signature made with creator.
|
||||||
* Signatures are returned in scriptSigRet (or returns false if scriptPubKey can't be signed),
|
* 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.
|
* Returns false if scriptPubKey could not be completely satisfied.
|
||||||
*/
|
*/
|
||||||
static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator& creator, const CScript& scriptPubKey,
|
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;
|
CScript scriptRet;
|
||||||
uint160 h160;
|
uint160 h160;
|
||||||
|
@ -108,15 +108,15 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
|
||||||
|
|
||||||
switch (whichTypeRet)
|
switch (whichTypeRet)
|
||||||
{
|
{
|
||||||
case TX_NONSTANDARD:
|
case TxoutType::NONSTANDARD:
|
||||||
case TX_NULL_DATA:
|
case TxoutType::NULL_DATA:
|
||||||
case TX_WITNESS_UNKNOWN:
|
case TxoutType::WITNESS_UNKNOWN:
|
||||||
return false;
|
return false;
|
||||||
case TX_PUBKEY:
|
case TxoutType::PUBKEY:
|
||||||
if (!CreateSig(creator, sigdata, provider, sig, CPubKey(vSolutions[0]), scriptPubKey, sigversion)) return false;
|
if (!CreateSig(creator, sigdata, provider, sig, CPubKey(vSolutions[0]), scriptPubKey, sigversion)) return false;
|
||||||
ret.push_back(std::move(sig));
|
ret.push_back(std::move(sig));
|
||||||
return true;
|
return true;
|
||||||
case TX_PUBKEYHASH: {
|
case TxoutType::PUBKEYHASH: {
|
||||||
CKeyID keyID = CKeyID(uint160(vSolutions[0]));
|
CKeyID keyID = CKeyID(uint160(vSolutions[0]));
|
||||||
CPubKey pubkey;
|
CPubKey pubkey;
|
||||||
if (!GetPubKey(provider, sigdata, keyID, pubkey)) {
|
if (!GetPubKey(provider, sigdata, keyID, pubkey)) {
|
||||||
|
@ -129,7 +129,7 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
|
||||||
ret.push_back(ToByteVector(pubkey));
|
ret.push_back(ToByteVector(pubkey));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case TX_SCRIPTHASH:
|
case TxoutType::SCRIPTHASH:
|
||||||
h160 = uint160(vSolutions[0]);
|
h160 = uint160(vSolutions[0]);
|
||||||
if (GetCScript(provider, sigdata, CScriptID{h160}, scriptRet)) {
|
if (GetCScript(provider, sigdata, CScriptID{h160}, scriptRet)) {
|
||||||
ret.push_back(std::vector<unsigned char>(scriptRet.begin(), scriptRet.end()));
|
ret.push_back(std::vector<unsigned char>(scriptRet.begin(), scriptRet.end()));
|
||||||
|
@ -139,7 +139,7 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
|
||||||
sigdata.missing_redeem_script = h160;
|
sigdata.missing_redeem_script = h160;
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case TX_MULTISIG: {
|
case TxoutType::MULTISIG: {
|
||||||
size_t required = vSolutions.front()[0];
|
size_t required = vSolutions.front()[0];
|
||||||
ret.push_back(valtype()); // workaround CHECKMULTISIG bug
|
ret.push_back(valtype()); // workaround CHECKMULTISIG bug
|
||||||
for (size_t i = 1; i < vSolutions.size() - 1; ++i) {
|
for (size_t i = 1; i < vSolutions.size() - 1; ++i) {
|
||||||
|
@ -159,11 +159,11 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
|
||||||
}
|
}
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
case TX_WITNESS_V0_KEYHASH:
|
case TxoutType::WITNESS_V0_KEYHASH:
|
||||||
ret.push_back(vSolutions[0]);
|
ret.push_back(vSolutions[0]);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case TX_WITNESS_V0_SCRIPTHASH:
|
case TxoutType::WITNESS_V0_SCRIPTHASH:
|
||||||
CRIPEMD160().Write(&vSolutions[0][0], vSolutions[0].size()).Finalize(h160.begin());
|
CRIPEMD160().Write(&vSolutions[0][0], vSolutions[0].size()).Finalize(h160.begin());
|
||||||
if (GetCScript(provider, sigdata, CScriptID{h160}, scriptRet)) {
|
if (GetCScript(provider, sigdata, CScriptID{h160}, scriptRet)) {
|
||||||
ret.push_back(std::vector<unsigned char>(scriptRet.begin(), scriptRet.end()));
|
ret.push_back(std::vector<unsigned char>(scriptRet.begin(), scriptRet.end()));
|
||||||
|
@ -198,44 +198,44 @@ bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreato
|
||||||
if (sigdata.complete) return true;
|
if (sigdata.complete) return true;
|
||||||
|
|
||||||
std::vector<valtype> result;
|
std::vector<valtype> result;
|
||||||
txnouttype whichType;
|
TxoutType whichType;
|
||||||
bool solved = SignStep(provider, creator, fromPubKey, result, whichType, SigVersion::BASE, sigdata);
|
bool solved = SignStep(provider, creator, fromPubKey, result, whichType, SigVersion::BASE, sigdata);
|
||||||
bool P2SH = false;
|
bool P2SH = false;
|
||||||
CScript subscript;
|
CScript subscript;
|
||||||
sigdata.scriptWitness.stack.clear();
|
sigdata.scriptWitness.stack.clear();
|
||||||
|
|
||||||
if (solved && whichType == TX_SCRIPTHASH)
|
if (solved && whichType == TxoutType::SCRIPTHASH)
|
||||||
{
|
{
|
||||||
// Solver returns the subscript that needs to be evaluated;
|
// Solver returns the subscript that needs to be evaluated;
|
||||||
// the final scriptSig is the signatures from that
|
// the final scriptSig is the signatures from that
|
||||||
// and then the serialized subscript:
|
// and then the serialized subscript:
|
||||||
subscript = CScript(result[0].begin(), result[0].end());
|
subscript = CScript(result[0].begin(), result[0].end());
|
||||||
sigdata.redeem_script = subscript;
|
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;
|
P2SH = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (solved && whichType == TX_WITNESS_V0_KEYHASH)
|
if (solved && whichType == TxoutType::WITNESS_V0_KEYHASH)
|
||||||
{
|
{
|
||||||
CScript witnessscript;
|
CScript witnessscript;
|
||||||
witnessscript << OP_DUP << OP_HASH160 << ToByteVector(result[0]) << OP_EQUALVERIFY << OP_CHECKSIG;
|
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);
|
solved = solved && SignStep(provider, creator, witnessscript, result, subType, SigVersion::WITNESS_V0, sigdata);
|
||||||
sigdata.scriptWitness.stack = result;
|
sigdata.scriptWitness.stack = result;
|
||||||
sigdata.witness = true;
|
sigdata.witness = true;
|
||||||
result.clear();
|
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());
|
CScript witnessscript(result[0].begin(), result[0].end());
|
||||||
sigdata.witness_script = witnessscript;
|
sigdata.witness_script = witnessscript;
|
||||||
txnouttype subType;
|
TxoutType 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;
|
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()));
|
result.push_back(std::vector<unsigned char>(witnessscript.begin(), witnessscript.end()));
|
||||||
sigdata.scriptWitness.stack = result;
|
sigdata.scriptWitness.stack = result;
|
||||||
sigdata.witness = true;
|
sigdata.witness = true;
|
||||||
result.clear();
|
result.clear();
|
||||||
} else if (solved && whichType == TX_WITNESS_UNKNOWN) {
|
} else if (solved && whichType == TxoutType::WITNESS_UNKNOWN) {
|
||||||
sigdata.witness = true;
|
sigdata.witness = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,11 +301,11 @@ SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nI
|
||||||
|
|
||||||
// Get scripts
|
// Get scripts
|
||||||
std::vector<std::vector<unsigned char>> solutions;
|
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;
|
SigVersion sigversion = SigVersion::BASE;
|
||||||
CScript next_script = txout.scriptPubKey;
|
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
|
// Get the redeemScript
|
||||||
CScript redeem_script(stack.script.back().begin(), stack.script.back().end());
|
CScript redeem_script(stack.script.back().begin(), stack.script.back().end());
|
||||||
data.redeem_script = redeem_script;
|
data.redeem_script = redeem_script;
|
||||||
|
@ -315,7 +315,7 @@ SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nI
|
||||||
script_type = Solver(next_script, solutions);
|
script_type = Solver(next_script, solutions);
|
||||||
stack.script.pop_back();
|
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
|
// Get the witnessScript
|
||||||
CScript witness_script(stack.witness.back().begin(), stack.witness.back().end());
|
CScript witness_script(stack.witness.back().begin(), stack.witness.back().end());
|
||||||
data.witness_script = witness_script;
|
data.witness_script = witness_script;
|
||||||
|
@ -328,7 +328,7 @@ SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nI
|
||||||
stack.witness.clear();
|
stack.witness.clear();
|
||||||
sigversion = SigVersion::WITNESS_V0;
|
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:
|
// Build a map of pubkey -> signature by matching sigs to pubkeys:
|
||||||
assert(solutions.size() > 1);
|
assert(solutions.size() > 1);
|
||||||
unsigned int num_pubkeys = solutions.size()-2;
|
unsigned int num_pubkeys = solutions.size()-2;
|
||||||
|
@ -454,13 +454,13 @@ bool IsSegWitOutput(const SigningProvider& provider, const CScript& script)
|
||||||
{
|
{
|
||||||
std::vector<valtype> solutions;
|
std::vector<valtype> solutions;
|
||||||
auto whichtype = Solver(script, 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 == TxoutType::WITNESS_V0_SCRIPTHASH || whichtype == TxoutType::WITNESS_V0_KEYHASH || whichtype == TxoutType::WITNESS_UNKNOWN) return true;
|
||||||
if (whichtype == TX_SCRIPTHASH) {
|
if (whichtype == TxoutType::SCRIPTHASH) {
|
||||||
auto h160 = uint160(solutions[0]);
|
auto h160 = uint160(solutions[0]);
|
||||||
CScript subscript;
|
CScript subscript;
|
||||||
if (provider.GetCScript(CScriptID{h160}, subscript)) {
|
if (provider.GetCScript(CScriptID{h160}, subscript)) {
|
||||||
whichtype = Solver(subscript, solutions);
|
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;
|
return false;
|
||||||
|
|
|
@ -43,19 +43,19 @@ WitnessV0ScriptHash::WitnessV0ScriptHash(const CScript& in)
|
||||||
CSHA256().Write(in.data(), in.size()).Finalize(begin());
|
CSHA256().Write(in.data(), in.size()).Finalize(begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetTxnOutputType(txnouttype t)
|
std::string GetTxnOutputType(TxoutType t)
|
||||||
{
|
{
|
||||||
switch (t)
|
switch (t)
|
||||||
{
|
{
|
||||||
case TX_NONSTANDARD: return "nonstandard";
|
case TxoutType::NONSTANDARD: return "nonstandard";
|
||||||
case TX_PUBKEY: return "pubkey";
|
case TxoutType::PUBKEY: return "pubkey";
|
||||||
case TX_PUBKEYHASH: return "pubkeyhash";
|
case TxoutType::PUBKEYHASH: return "pubkeyhash";
|
||||||
case TX_SCRIPTHASH: return "scripthash";
|
case TxoutType::SCRIPTHASH: return "scripthash";
|
||||||
case TX_MULTISIG: return "multisig";
|
case TxoutType::MULTISIG: return "multisig";
|
||||||
case TX_NULL_DATA: return "nulldata";
|
case TxoutType::NULL_DATA: return "nulldata";
|
||||||
case TX_WITNESS_V0_KEYHASH: return "witness_v0_keyhash";
|
case TxoutType::WITNESS_V0_KEYHASH: return "witness_v0_keyhash";
|
||||||
case TX_WITNESS_V0_SCRIPTHASH: return "witness_v0_scripthash";
|
case TxoutType::WITNESS_V0_SCRIPTHASH: return "witness_v0_scripthash";
|
||||||
case TX_WITNESS_UNKNOWN: return "witness_unknown";
|
case TxoutType::WITNESS_UNKNOWN: return "witness_unknown";
|
||||||
} // 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);
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ static bool MatchMultisig(const CScript& script, unsigned int& required, std::ve
|
||||||
return (it + 1 == script.end());
|
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();
|
vSolutionsRet.clear();
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ txnouttype Solver(const CScript& scriptPubKey, std::vector<std::vector<unsigned
|
||||||
{
|
{
|
||||||
std::vector<unsigned char> hashBytes(scriptPubKey.begin()+2, scriptPubKey.begin()+22);
|
std::vector<unsigned char> hashBytes(scriptPubKey.begin()+2, scriptPubKey.begin()+22);
|
||||||
vSolutionsRet.push_back(hashBytes);
|
vSolutionsRet.push_back(hashBytes);
|
||||||
return TX_SCRIPTHASH;
|
return TxoutType::SCRIPTHASH;
|
||||||
}
|
}
|
||||||
|
|
||||||
int witnessversion;
|
int witnessversion;
|
||||||
|
@ -124,18 +124,18 @@ txnouttype Solver(const CScript& scriptPubKey, std::vector<std::vector<unsigned
|
||||||
if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
|
if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
|
||||||
if (witnessversion == 0 && witnessprogram.size() == WITNESS_V0_KEYHASH_SIZE) {
|
if (witnessversion == 0 && witnessprogram.size() == WITNESS_V0_KEYHASH_SIZE) {
|
||||||
vSolutionsRet.push_back(witnessprogram);
|
vSolutionsRet.push_back(witnessprogram);
|
||||||
return TX_WITNESS_V0_KEYHASH;
|
return TxoutType::WITNESS_V0_KEYHASH;
|
||||||
}
|
}
|
||||||
if (witnessversion == 0 && witnessprogram.size() == WITNESS_V0_SCRIPTHASH_SIZE) {
|
if (witnessversion == 0 && witnessprogram.size() == WITNESS_V0_SCRIPTHASH_SIZE) {
|
||||||
vSolutionsRet.push_back(witnessprogram);
|
vSolutionsRet.push_back(witnessprogram);
|
||||||
return TX_WITNESS_V0_SCRIPTHASH;
|
return TxoutType::WITNESS_V0_SCRIPTHASH;
|
||||||
}
|
}
|
||||||
if (witnessversion != 0) {
|
if (witnessversion != 0) {
|
||||||
vSolutionsRet.push_back(std::vector<unsigned char>{(unsigned char)witnessversion});
|
vSolutionsRet.push_back(std::vector<unsigned char>{(unsigned char)witnessversion});
|
||||||
vSolutionsRet.push_back(std::move(witnessprogram));
|
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
|
// Provably prunable, data-carrying output
|
||||||
|
@ -144,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
|
// byte passes the IsPushOnly() test we don't care what exactly is in the
|
||||||
// script.
|
// script.
|
||||||
if (scriptPubKey.size() >= 1 && scriptPubKey[0] == OP_RETURN && scriptPubKey.IsPushOnly(scriptPubKey.begin()+1)) {
|
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;
|
std::vector<unsigned char> data;
|
||||||
if (MatchPayToPubkey(scriptPubKey, data)) {
|
if (MatchPayToPubkey(scriptPubKey, data)) {
|
||||||
vSolutionsRet.push_back(std::move(data));
|
vSolutionsRet.push_back(std::move(data));
|
||||||
return TX_PUBKEY;
|
return TxoutType::PUBKEY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MatchPayToPubkeyHash(scriptPubKey, data)) {
|
if (MatchPayToPubkeyHash(scriptPubKey, data)) {
|
||||||
vSolutionsRet.push_back(std::move(data));
|
vSolutionsRet.push_back(std::move(data));
|
||||||
return TX_PUBKEYHASH;
|
return TxoutType::PUBKEYHASH;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int required;
|
unsigned int required;
|
||||||
|
@ -164,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.push_back({static_cast<unsigned char>(required)}); // safe as required is in range 1..16
|
||||||
vSolutionsRet.insert(vSolutionsRet.end(), keys.begin(), keys.end());
|
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
|
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();
|
vSolutionsRet.clear();
|
||||||
return TX_NONSTANDARD;
|
return TxoutType::NONSTANDARD;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
|
bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
|
||||||
{
|
{
|
||||||
std::vector<valtype> vSolutions;
|
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]);
|
CPubKey pubKey(vSolutions[0]);
|
||||||
if (!pubKey.IsValid())
|
if (!pubKey.IsValid())
|
||||||
return false;
|
return false;
|
||||||
|
@ -184,26 +184,26 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
|
||||||
addressRet = PKHash(pubKey);
|
addressRet = PKHash(pubKey);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (whichType == TX_PUBKEYHASH)
|
else if (whichType == TxoutType::PUBKEYHASH)
|
||||||
{
|
{
|
||||||
addressRet = PKHash(uint160(vSolutions[0]));
|
addressRet = PKHash(uint160(vSolutions[0]));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (whichType == TX_SCRIPTHASH)
|
else if (whichType == TxoutType::SCRIPTHASH)
|
||||||
{
|
{
|
||||||
addressRet = ScriptHash(uint160(vSolutions[0]));
|
addressRet = ScriptHash(uint160(vSolutions[0]));
|
||||||
return true;
|
return true;
|
||||||
} else if (whichType == TX_WITNESS_V0_KEYHASH) {
|
} else if (whichType == TxoutType::WITNESS_V0_KEYHASH) {
|
||||||
WitnessV0KeyHash hash;
|
WitnessV0KeyHash hash;
|
||||||
std::copy(vSolutions[0].begin(), vSolutions[0].end(), hash.begin());
|
std::copy(vSolutions[0].begin(), vSolutions[0].end(), hash.begin());
|
||||||
addressRet = hash;
|
addressRet = hash;
|
||||||
return true;
|
return true;
|
||||||
} else if (whichType == TX_WITNESS_V0_SCRIPTHASH) {
|
} else if (whichType == TxoutType::WITNESS_V0_SCRIPTHASH) {
|
||||||
WitnessV0ScriptHash hash;
|
WitnessV0ScriptHash hash;
|
||||||
std::copy(vSolutions[0].begin(), vSolutions[0].end(), hash.begin());
|
std::copy(vSolutions[0].begin(), vSolutions[0].end(), hash.begin());
|
||||||
addressRet = hash;
|
addressRet = hash;
|
||||||
return true;
|
return true;
|
||||||
} else if (whichType == TX_WITNESS_UNKNOWN) {
|
} else if (whichType == TxoutType::WITNESS_UNKNOWN) {
|
||||||
WitnessUnknown unk;
|
WitnessUnknown unk;
|
||||||
unk.version = vSolutions[0][0];
|
unk.version = vSolutions[0][0];
|
||||||
std::copy(vSolutions[1].begin(), vSolutions[1].end(), unk.program);
|
std::copy(vSolutions[1].begin(), vSolutions[1].end(), unk.program);
|
||||||
|
@ -215,19 +215,19 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
|
||||||
return false;
|
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();
|
addressRet.clear();
|
||||||
std::vector<valtype> vSolutions;
|
std::vector<valtype> vSolutions;
|
||||||
typeRet = Solver(scriptPubKey, vSolutions);
|
typeRet = Solver(scriptPubKey, vSolutions);
|
||||||
if (typeRet == TX_NONSTANDARD) {
|
if (typeRet == TxoutType::NONSTANDARD) {
|
||||||
return false;
|
return false;
|
||||||
} else if (typeRet == TX_NULL_DATA) {
|
} else if (typeRet == TxoutType::NULL_DATA) {
|
||||||
// This is data, not addresses
|
// This is data, not addresses
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeRet == TX_MULTISIG)
|
if (typeRet == TxoutType::MULTISIG)
|
||||||
{
|
{
|
||||||
nRequiredRet = vSolutions.front()[0];
|
nRequiredRet = vSolutions.front()[0];
|
||||||
for (unsigned int i = 1; i < vSolutions.size()-1; i++)
|
for (unsigned int i = 1; i < vSolutions.size()-1; i++)
|
||||||
|
@ -319,10 +319,10 @@ CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys)
|
||||||
CScript GetScriptForWitness(const CScript& redeemscript)
|
CScript GetScriptForWitness(const CScript& redeemscript)
|
||||||
{
|
{
|
||||||
std::vector<std::vector<unsigned char> > vSolutions;
|
std::vector<std::vector<unsigned char> > vSolutions;
|
||||||
txnouttype typ = Solver(redeemscript, vSolutions);
|
TxoutType typ = Solver(redeemscript, vSolutions);
|
||||||
if (typ == TX_PUBKEY) {
|
if (typ == TxoutType::PUBKEY) {
|
||||||
return GetScriptForDestination(WitnessV0KeyHash(Hash160(vSolutions[0].begin(), vSolutions[0].end())));
|
return GetScriptForDestination(WitnessV0KeyHash(Hash160(vSolutions[0].begin(), vSolutions[0].end())));
|
||||||
} else if (typ == TX_PUBKEYHASH) {
|
} else if (typ == TxoutType::PUBKEYHASH) {
|
||||||
return GetScriptForDestination(WitnessV0KeyHash(uint160{vSolutions[0]}));
|
return GetScriptForDestination(WitnessV0KeyHash(uint160{vSolutions[0]}));
|
||||||
}
|
}
|
||||||
return GetScriptForDestination(WitnessV0ScriptHash(redeemscript));
|
return GetScriptForDestination(WitnessV0ScriptHash(redeemscript));
|
||||||
|
|
|
@ -99,11 +99,11 @@ static const unsigned int MAX_OP_RETURN_RELAY = 83;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A data carrying output is an unspendable output containing data. The script
|
* 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;
|
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;
|
extern unsigned nMaxDatacarrierBytes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -116,17 +116,17 @@ extern unsigned nMaxDatacarrierBytes;
|
||||||
*/
|
*/
|
||||||
static const unsigned int MANDATORY_SCRIPT_VERIFY_FLAGS = SCRIPT_VERIFY_P2SH;
|
static const unsigned int MANDATORY_SCRIPT_VERIFY_FLAGS = SCRIPT_VERIFY_P2SH;
|
||||||
|
|
||||||
enum txnouttype {
|
enum class TxoutType {
|
||||||
TX_NONSTANDARD,
|
NONSTANDARD,
|
||||||
// 'standard' transaction types:
|
// 'standard' transaction types:
|
||||||
TX_PUBKEY,
|
PUBKEY,
|
||||||
TX_PUBKEYHASH,
|
PUBKEYHASH,
|
||||||
TX_SCRIPTHASH,
|
SCRIPTHASH,
|
||||||
TX_MULTISIG,
|
MULTISIG,
|
||||||
TX_NULL_DATA, //!< unspendable OP_RETURN script that carries data
|
NULL_DATA, //!< unspendable OP_RETURN script that carries data
|
||||||
TX_WITNESS_V0_SCRIPTHASH,
|
WITNESS_V0_SCRIPTHASH,
|
||||||
TX_WITNESS_V0_KEYHASH,
|
WITNESS_V0_KEYHASH,
|
||||||
TX_WITNESS_UNKNOWN, //!< Only for Witness versions not already defined above
|
WITNESS_UNKNOWN, //!< Only for Witness versions not already defined above
|
||||||
};
|
};
|
||||||
|
|
||||||
class CNoDestination {
|
class CNoDestination {
|
||||||
|
@ -199,11 +199,11 @@ struct WitnessUnknown
|
||||||
/**
|
/**
|
||||||
* A txout script template with a specific destination. It is either:
|
* A txout script template with a specific destination. It is either:
|
||||||
* * CNoDestination: no destination set
|
* * CNoDestination: no destination set
|
||||||
* * PKHash: TX_PUBKEYHASH destination (P2PKH)
|
* * PKHash: TxoutType::PUBKEYHASH destination (P2PKH)
|
||||||
* * ScriptHash: TX_SCRIPTHASH destination (P2SH)
|
* * ScriptHash: TxoutType::SCRIPTHASH destination (P2SH)
|
||||||
* * WitnessV0ScriptHash: TX_WITNESS_V0_SCRIPTHASH destination (P2WSH)
|
* * WitnessV0ScriptHash: TxoutType::WITNESS_V0_SCRIPTHASH destination (P2WSH)
|
||||||
* * WitnessV0KeyHash: TX_WITNESS_V0_KEYHASH destination (P2WPKH)
|
* * WitnessV0KeyHash: TxoutType::WITNESS_V0_KEYHASH destination (P2WPKH)
|
||||||
* * WitnessUnknown: TX_WITNESS_UNKNOWN destination (P2W???)
|
* * WitnessUnknown: TxoutType::WITNESS_UNKNOWN destination (P2W???)
|
||||||
* A CTxDestination is the internal data type encoded in a bitcoin address
|
* A CTxDestination is the internal data type encoded in a bitcoin address
|
||||||
*/
|
*/
|
||||||
typedef boost::variant<CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessUnknown> CTxDestination;
|
typedef boost::variant<CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessUnknown> CTxDestination;
|
||||||
|
@ -211,8 +211,8 @@ typedef boost::variant<CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash,
|
||||||
/** Check whether a CTxDestination is a CNoDestination. */
|
/** Check whether a CTxDestination is a CNoDestination. */
|
||||||
bool IsValidDestination(const CTxDestination& dest);
|
bool IsValidDestination(const CTxDestination& dest);
|
||||||
|
|
||||||
/** Get the name of a txnouttype as a string */
|
/** Get the name of a TxoutType as a string */
|
||||||
std::string GetTxnOutputType(txnouttype t);
|
std::string GetTxnOutputType(TxoutType t);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a scriptPubKey and identify script type for standard scripts. If
|
* Parse a scriptPubKey and identify script type for standard scripts. If
|
||||||
|
@ -222,9 +222,9 @@ std::string GetTxnOutputType(txnouttype t);
|
||||||
*
|
*
|
||||||
* @param[in] scriptPubKey Script to parse
|
* @param[in] scriptPubKey Script to parse
|
||||||
* @param[out] vSolutionsRet Vector of parsed pubkeys and hashes
|
* @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
|
* Parse a standard scriptPubKey for the destination address. Assigns result to
|
||||||
|
@ -245,7 +245,7 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
|
||||||
* encodable as an address) with key identifiers (of keys involved in a
|
* encodable as an address) with key identifiers (of keys involved in a
|
||||||
* CScript), and its use should be phased out.
|
* 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
|
* Generate a Bitcoin scriptPubKey for the given CTxDestination. Returns a P2PKH
|
||||||
|
|
|
@ -157,25 +157,25 @@ void test_one_input(const std::vector<uint8_t>& buffer)
|
||||||
assert(ok_add_key_pubkey);
|
assert(ok_add_key_pubkey);
|
||||||
assert(fillable_signing_provider_pub.HaveKey(pubkey.GetID()));
|
assert(fillable_signing_provider_pub.HaveKey(pubkey.GetID()));
|
||||||
|
|
||||||
txnouttype which_type_tx_pubkey;
|
TxoutType which_type_tx_pubkey;
|
||||||
const bool is_standard_tx_pubkey = IsStandard(tx_pubkey_script, which_type_tx_pubkey);
|
const bool is_standard_tx_pubkey = IsStandard(tx_pubkey_script, which_type_tx_pubkey);
|
||||||
assert(is_standard_tx_pubkey);
|
assert(is_standard_tx_pubkey);
|
||||||
assert(which_type_tx_pubkey == TX_PUBKEY);
|
assert(which_type_tx_pubkey == TxoutType::PUBKEY);
|
||||||
|
|
||||||
txnouttype which_type_tx_multisig;
|
TxoutType which_type_tx_multisig;
|
||||||
const bool is_standard_tx_multisig = IsStandard(tx_multisig_script, which_type_tx_multisig);
|
const bool is_standard_tx_multisig = IsStandard(tx_multisig_script, which_type_tx_multisig);
|
||||||
assert(is_standard_tx_multisig);
|
assert(is_standard_tx_multisig);
|
||||||
assert(which_type_tx_multisig == TX_MULTISIG);
|
assert(which_type_tx_multisig == TxoutType::MULTISIG);
|
||||||
|
|
||||||
std::vector<std::vector<unsigned char>> v_solutions_ret_tx_pubkey;
|
std::vector<std::vector<unsigned char>> v_solutions_ret_tx_pubkey;
|
||||||
const txnouttype outtype_tx_pubkey = Solver(tx_pubkey_script, v_solutions_ret_tx_pubkey);
|
const TxoutType outtype_tx_pubkey = Solver(tx_pubkey_script, v_solutions_ret_tx_pubkey);
|
||||||
assert(outtype_tx_pubkey == TX_PUBKEY);
|
assert(outtype_tx_pubkey == TxoutType::PUBKEY);
|
||||||
assert(v_solutions_ret_tx_pubkey.size() == 1);
|
assert(v_solutions_ret_tx_pubkey.size() == 1);
|
||||||
assert(v_solutions_ret_tx_pubkey[0].size() == 33);
|
assert(v_solutions_ret_tx_pubkey[0].size() == 33);
|
||||||
|
|
||||||
std::vector<std::vector<unsigned char>> v_solutions_ret_tx_multisig;
|
std::vector<std::vector<unsigned char>> v_solutions_ret_tx_multisig;
|
||||||
const txnouttype outtype_tx_multisig = Solver(tx_multisig_script, v_solutions_ret_tx_multisig);
|
const TxoutType outtype_tx_multisig = Solver(tx_multisig_script, v_solutions_ret_tx_multisig);
|
||||||
assert(outtype_tx_multisig == TX_MULTISIG);
|
assert(outtype_tx_multisig == TxoutType::MULTISIG);
|
||||||
assert(v_solutions_ret_tx_multisig.size() == 3);
|
assert(v_solutions_ret_tx_multisig.size() == 3);
|
||||||
assert(v_solutions_ret_tx_multisig[0].size() == 1);
|
assert(v_solutions_ret_tx_multisig[0].size() == 1);
|
||||||
assert(v_solutions_ret_tx_multisig[1].size() == 33);
|
assert(v_solutions_ret_tx_multisig[1].size() == 33);
|
||||||
|
|
|
@ -58,7 +58,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
|
||||||
CTxDestination address;
|
CTxDestination address;
|
||||||
(void)ExtractDestination(script, address);
|
(void)ExtractDestination(script, address);
|
||||||
|
|
||||||
txnouttype type_ret;
|
TxoutType type_ret;
|
||||||
std::vector<CTxDestination> addresses;
|
std::vector<CTxDestination> addresses;
|
||||||
int required_ret;
|
int required_ret;
|
||||||
(void)ExtractDestinations(script, type_ret, addresses, required_ret);
|
(void)ExtractDestinations(script, type_ret, addresses, required_ret);
|
||||||
|
@ -72,7 +72,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
|
||||||
|
|
||||||
(void)IsSolvable(signing_provider, script);
|
(void)IsSolvable(signing_provider, script);
|
||||||
|
|
||||||
txnouttype which_type;
|
TxoutType which_type;
|
||||||
(void)IsStandard(script, which_type);
|
(void)IsStandard(script, which_type);
|
||||||
|
|
||||||
(void)RecursiveDynamicUsage(script);
|
(void)RecursiveDynamicUsage(script);
|
||||||
|
|
|
@ -141,7 +141,7 @@ BOOST_AUTO_TEST_CASE(multisig_IsStandard)
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
key[i].MakeNewKey(true);
|
key[i].MakeNewKey(true);
|
||||||
|
|
||||||
txnouttype whichType;
|
TxoutType whichType;
|
||||||
|
|
||||||
CScript a_and_b;
|
CScript a_and_b;
|
||||||
a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
|
a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
|
||||||
|
|
|
@ -31,35 +31,35 @@ BOOST_AUTO_TEST_CASE(script_standard_Solver_success)
|
||||||
CScript s;
|
CScript s;
|
||||||
std::vector<std::vector<unsigned char> > solutions;
|
std::vector<std::vector<unsigned char> > solutions;
|
||||||
|
|
||||||
// TX_PUBKEY
|
// TxoutType::PUBKEY
|
||||||
s.clear();
|
s.clear();
|
||||||
s << ToByteVector(pubkeys[0]) << OP_CHECKSIG;
|
s << ToByteVector(pubkeys[0]) << OP_CHECKSIG;
|
||||||
BOOST_CHECK_EQUAL(Solver(s, solutions), TX_PUBKEY);
|
BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::PUBKEY);
|
||||||
BOOST_CHECK_EQUAL(solutions.size(), 1U);
|
BOOST_CHECK_EQUAL(solutions.size(), 1U);
|
||||||
BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0]));
|
BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0]));
|
||||||
|
|
||||||
// TX_PUBKEYHASH
|
// TxoutType::PUBKEYHASH
|
||||||
s.clear();
|
s.clear();
|
||||||
s << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
|
s << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
|
||||||
BOOST_CHECK_EQUAL(Solver(s, solutions), TX_PUBKEYHASH);
|
BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::PUBKEYHASH);
|
||||||
BOOST_CHECK_EQUAL(solutions.size(), 1U);
|
BOOST_CHECK_EQUAL(solutions.size(), 1U);
|
||||||
BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0].GetID()));
|
BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0].GetID()));
|
||||||
|
|
||||||
// TX_SCRIPTHASH
|
// TxoutType::SCRIPTHASH
|
||||||
CScript redeemScript(s); // initialize with leftover P2PKH script
|
CScript redeemScript(s); // initialize with leftover P2PKH script
|
||||||
s.clear();
|
s.clear();
|
||||||
s << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
|
s << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
|
||||||
BOOST_CHECK_EQUAL(Solver(s, solutions), TX_SCRIPTHASH);
|
BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::SCRIPTHASH);
|
||||||
BOOST_CHECK_EQUAL(solutions.size(), 1U);
|
BOOST_CHECK_EQUAL(solutions.size(), 1U);
|
||||||
BOOST_CHECK(solutions[0] == ToByteVector(CScriptID(redeemScript)));
|
BOOST_CHECK(solutions[0] == ToByteVector(CScriptID(redeemScript)));
|
||||||
|
|
||||||
// TX_MULTISIG
|
// TxoutType::MULTISIG
|
||||||
s.clear();
|
s.clear();
|
||||||
s << OP_1 <<
|
s << OP_1 <<
|
||||||
ToByteVector(pubkeys[0]) <<
|
ToByteVector(pubkeys[0]) <<
|
||||||
ToByteVector(pubkeys[1]) <<
|
ToByteVector(pubkeys[1]) <<
|
||||||
OP_2 << OP_CHECKMULTISIG;
|
OP_2 << OP_CHECKMULTISIG;
|
||||||
BOOST_CHECK_EQUAL(Solver(s, solutions), TX_MULTISIG);
|
BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::MULTISIG);
|
||||||
BOOST_CHECK_EQUAL(solutions.size(), 4U);
|
BOOST_CHECK_EQUAL(solutions.size(), 4U);
|
||||||
BOOST_CHECK(solutions[0] == std::vector<unsigned char>({1}));
|
BOOST_CHECK(solutions[0] == std::vector<unsigned char>({1}));
|
||||||
BOOST_CHECK(solutions[1] == ToByteVector(pubkeys[0]));
|
BOOST_CHECK(solutions[1] == ToByteVector(pubkeys[0]));
|
||||||
|
@ -72,7 +72,7 @@ BOOST_AUTO_TEST_CASE(script_standard_Solver_success)
|
||||||
ToByteVector(pubkeys[1]) <<
|
ToByteVector(pubkeys[1]) <<
|
||||||
ToByteVector(pubkeys[2]) <<
|
ToByteVector(pubkeys[2]) <<
|
||||||
OP_3 << OP_CHECKMULTISIG;
|
OP_3 << OP_CHECKMULTISIG;
|
||||||
BOOST_CHECK_EQUAL(Solver(s, solutions), TX_MULTISIG);
|
BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::MULTISIG);
|
||||||
BOOST_CHECK_EQUAL(solutions.size(), 5U);
|
BOOST_CHECK_EQUAL(solutions.size(), 5U);
|
||||||
BOOST_CHECK(solutions[0] == std::vector<unsigned char>({2}));
|
BOOST_CHECK(solutions[0] == std::vector<unsigned char>({2}));
|
||||||
BOOST_CHECK(solutions[1] == ToByteVector(pubkeys[0]));
|
BOOST_CHECK(solutions[1] == ToByteVector(pubkeys[0]));
|
||||||
|
@ -80,37 +80,37 @@ BOOST_AUTO_TEST_CASE(script_standard_Solver_success)
|
||||||
BOOST_CHECK(solutions[3] == ToByteVector(pubkeys[2]));
|
BOOST_CHECK(solutions[3] == ToByteVector(pubkeys[2]));
|
||||||
BOOST_CHECK(solutions[4] == std::vector<unsigned char>({3}));
|
BOOST_CHECK(solutions[4] == std::vector<unsigned char>({3}));
|
||||||
|
|
||||||
// TX_NULL_DATA
|
// TxoutType::NULL_DATA
|
||||||
s.clear();
|
s.clear();
|
||||||
s << OP_RETURN <<
|
s << OP_RETURN <<
|
||||||
std::vector<unsigned char>({0}) <<
|
std::vector<unsigned char>({0}) <<
|
||||||
std::vector<unsigned char>({75}) <<
|
std::vector<unsigned char>({75}) <<
|
||||||
std::vector<unsigned char>({255});
|
std::vector<unsigned char>({255});
|
||||||
BOOST_CHECK_EQUAL(Solver(s, solutions), TX_NULL_DATA);
|
BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NULL_DATA);
|
||||||
BOOST_CHECK_EQUAL(solutions.size(), 0U);
|
BOOST_CHECK_EQUAL(solutions.size(), 0U);
|
||||||
|
|
||||||
// TX_WITNESS_V0_KEYHASH
|
// TxoutType::WITNESS_V0_KEYHASH
|
||||||
s.clear();
|
s.clear();
|
||||||
s << OP_0 << ToByteVector(pubkeys[0].GetID());
|
s << OP_0 << ToByteVector(pubkeys[0].GetID());
|
||||||
BOOST_CHECK_EQUAL(Solver(s, solutions), TX_WITNESS_V0_KEYHASH);
|
BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::WITNESS_V0_KEYHASH);
|
||||||
BOOST_CHECK_EQUAL(solutions.size(), 1U);
|
BOOST_CHECK_EQUAL(solutions.size(), 1U);
|
||||||
BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0].GetID()));
|
BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0].GetID()));
|
||||||
|
|
||||||
// TX_WITNESS_V0_SCRIPTHASH
|
// TxoutType::WITNESS_V0_SCRIPTHASH
|
||||||
uint256 scriptHash;
|
uint256 scriptHash;
|
||||||
CSHA256().Write(&redeemScript[0], redeemScript.size())
|
CSHA256().Write(&redeemScript[0], redeemScript.size())
|
||||||
.Finalize(scriptHash.begin());
|
.Finalize(scriptHash.begin());
|
||||||
|
|
||||||
s.clear();
|
s.clear();
|
||||||
s << OP_0 << ToByteVector(scriptHash);
|
s << OP_0 << ToByteVector(scriptHash);
|
||||||
BOOST_CHECK_EQUAL(Solver(s, solutions), TX_WITNESS_V0_SCRIPTHASH);
|
BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::WITNESS_V0_SCRIPTHASH);
|
||||||
BOOST_CHECK_EQUAL(solutions.size(), 1U);
|
BOOST_CHECK_EQUAL(solutions.size(), 1U);
|
||||||
BOOST_CHECK(solutions[0] == ToByteVector(scriptHash));
|
BOOST_CHECK(solutions[0] == ToByteVector(scriptHash));
|
||||||
|
|
||||||
// TX_NONSTANDARD
|
// TxoutType::NONSTANDARD
|
||||||
s.clear();
|
s.clear();
|
||||||
s << OP_9 << OP_ADD << OP_11 << OP_EQUAL;
|
s << OP_9 << OP_ADD << OP_11 << OP_EQUAL;
|
||||||
BOOST_CHECK_EQUAL(Solver(s, solutions), TX_NONSTANDARD);
|
BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(script_standard_Solver_failure)
|
BOOST_AUTO_TEST_CASE(script_standard_Solver_failure)
|
||||||
|
@ -123,50 +123,50 @@ BOOST_AUTO_TEST_CASE(script_standard_Solver_failure)
|
||||||
CScript s;
|
CScript s;
|
||||||
std::vector<std::vector<unsigned char> > solutions;
|
std::vector<std::vector<unsigned char> > solutions;
|
||||||
|
|
||||||
// TX_PUBKEY with incorrectly sized pubkey
|
// TxoutType::PUBKEY with incorrectly sized pubkey
|
||||||
s.clear();
|
s.clear();
|
||||||
s << std::vector<unsigned char>(30, 0x01) << OP_CHECKSIG;
|
s << std::vector<unsigned char>(30, 0x01) << OP_CHECKSIG;
|
||||||
BOOST_CHECK_EQUAL(Solver(s, solutions), TX_NONSTANDARD);
|
BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
|
||||||
|
|
||||||
// TX_PUBKEYHASH with incorrectly sized key hash
|
// TxoutType::PUBKEYHASH with incorrectly sized key hash
|
||||||
s.clear();
|
s.clear();
|
||||||
s << OP_DUP << OP_HASH160 << ToByteVector(pubkey) << OP_EQUALVERIFY << OP_CHECKSIG;
|
s << OP_DUP << OP_HASH160 << ToByteVector(pubkey) << OP_EQUALVERIFY << OP_CHECKSIG;
|
||||||
BOOST_CHECK_EQUAL(Solver(s, solutions), TX_NONSTANDARD);
|
BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
|
||||||
|
|
||||||
// TX_SCRIPTHASH with incorrectly sized script hash
|
// TxoutType::SCRIPTHASH with incorrectly sized script hash
|
||||||
s.clear();
|
s.clear();
|
||||||
s << OP_HASH160 << std::vector<unsigned char>(21, 0x01) << OP_EQUAL;
|
s << OP_HASH160 << std::vector<unsigned char>(21, 0x01) << OP_EQUAL;
|
||||||
BOOST_CHECK_EQUAL(Solver(s, solutions), TX_NONSTANDARD);
|
BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
|
||||||
|
|
||||||
// TX_MULTISIG 0/2
|
// TxoutType::MULTISIG 0/2
|
||||||
s.clear();
|
s.clear();
|
||||||
s << OP_0 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG;
|
s << OP_0 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG;
|
||||||
BOOST_CHECK_EQUAL(Solver(s, solutions), TX_NONSTANDARD);
|
BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
|
||||||
|
|
||||||
// TX_MULTISIG 2/1
|
// TxoutType::MULTISIG 2/1
|
||||||
s.clear();
|
s.clear();
|
||||||
s << OP_2 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG;
|
s << OP_2 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG;
|
||||||
BOOST_CHECK_EQUAL(Solver(s, solutions), TX_NONSTANDARD);
|
BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
|
||||||
|
|
||||||
// TX_MULTISIG n = 2 with 1 pubkey
|
// TxoutType::MULTISIG n = 2 with 1 pubkey
|
||||||
s.clear();
|
s.clear();
|
||||||
s << OP_1 << ToByteVector(pubkey) << OP_2 << OP_CHECKMULTISIG;
|
s << OP_1 << ToByteVector(pubkey) << OP_2 << OP_CHECKMULTISIG;
|
||||||
BOOST_CHECK_EQUAL(Solver(s, solutions), TX_NONSTANDARD);
|
BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
|
||||||
|
|
||||||
// TX_MULTISIG n = 1 with 0 pubkeys
|
// TxoutType::MULTISIG n = 1 with 0 pubkeys
|
||||||
s.clear();
|
s.clear();
|
||||||
s << OP_1 << OP_1 << OP_CHECKMULTISIG;
|
s << OP_1 << OP_1 << OP_CHECKMULTISIG;
|
||||||
BOOST_CHECK_EQUAL(Solver(s, solutions), TX_NONSTANDARD);
|
BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
|
||||||
|
|
||||||
// TX_NULL_DATA with other opcodes
|
// TxoutType::NULL_DATA with other opcodes
|
||||||
s.clear();
|
s.clear();
|
||||||
s << OP_RETURN << std::vector<unsigned char>({75}) << OP_ADD;
|
s << OP_RETURN << std::vector<unsigned char>({75}) << OP_ADD;
|
||||||
BOOST_CHECK_EQUAL(Solver(s, solutions), TX_NONSTANDARD);
|
BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
|
||||||
|
|
||||||
// TX_WITNESS_UNKNOWN with incorrect program size
|
// TxoutType::WITNESS_UNKNOWN with incorrect program size
|
||||||
s.clear();
|
s.clear();
|
||||||
s << OP_0 << std::vector<unsigned char>(19, 0x01);
|
s << OP_0 << std::vector<unsigned char>(19, 0x01);
|
||||||
BOOST_CHECK_EQUAL(Solver(s, solutions), TX_NONSTANDARD);
|
BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(script_standard_ExtractDestination)
|
BOOST_AUTO_TEST_CASE(script_standard_ExtractDestination)
|
||||||
|
@ -179,21 +179,21 @@ BOOST_AUTO_TEST_CASE(script_standard_ExtractDestination)
|
||||||
CScript s;
|
CScript s;
|
||||||
CTxDestination address;
|
CTxDestination address;
|
||||||
|
|
||||||
// TX_PUBKEY
|
// TxoutType::PUBKEY
|
||||||
s.clear();
|
s.clear();
|
||||||
s << ToByteVector(pubkey) << OP_CHECKSIG;
|
s << ToByteVector(pubkey) << OP_CHECKSIG;
|
||||||
BOOST_CHECK(ExtractDestination(s, address));
|
BOOST_CHECK(ExtractDestination(s, address));
|
||||||
BOOST_CHECK(boost::get<PKHash>(&address) &&
|
BOOST_CHECK(boost::get<PKHash>(&address) &&
|
||||||
*boost::get<PKHash>(&address) == PKHash(pubkey));
|
*boost::get<PKHash>(&address) == PKHash(pubkey));
|
||||||
|
|
||||||
// TX_PUBKEYHASH
|
// TxoutType::PUBKEYHASH
|
||||||
s.clear();
|
s.clear();
|
||||||
s << OP_DUP << OP_HASH160 << ToByteVector(pubkey.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
|
s << OP_DUP << OP_HASH160 << ToByteVector(pubkey.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
|
||||||
BOOST_CHECK(ExtractDestination(s, address));
|
BOOST_CHECK(ExtractDestination(s, address));
|
||||||
BOOST_CHECK(boost::get<PKHash>(&address) &&
|
BOOST_CHECK(boost::get<PKHash>(&address) &&
|
||||||
*boost::get<PKHash>(&address) == PKHash(pubkey));
|
*boost::get<PKHash>(&address) == PKHash(pubkey));
|
||||||
|
|
||||||
// TX_SCRIPTHASH
|
// TxoutType::SCRIPTHASH
|
||||||
CScript redeemScript(s); // initialize with leftover P2PKH script
|
CScript redeemScript(s); // initialize with leftover P2PKH script
|
||||||
s.clear();
|
s.clear();
|
||||||
s << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
|
s << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
|
||||||
|
@ -201,17 +201,17 @@ BOOST_AUTO_TEST_CASE(script_standard_ExtractDestination)
|
||||||
BOOST_CHECK(boost::get<ScriptHash>(&address) &&
|
BOOST_CHECK(boost::get<ScriptHash>(&address) &&
|
||||||
*boost::get<ScriptHash>(&address) == ScriptHash(redeemScript));
|
*boost::get<ScriptHash>(&address) == ScriptHash(redeemScript));
|
||||||
|
|
||||||
// TX_MULTISIG
|
// TxoutType::MULTISIG
|
||||||
s.clear();
|
s.clear();
|
||||||
s << OP_1 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG;
|
s << OP_1 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG;
|
||||||
BOOST_CHECK(!ExtractDestination(s, address));
|
BOOST_CHECK(!ExtractDestination(s, address));
|
||||||
|
|
||||||
// TX_NULL_DATA
|
// TxoutType::NULL_DATA
|
||||||
s.clear();
|
s.clear();
|
||||||
s << OP_RETURN << std::vector<unsigned char>({75});
|
s << OP_RETURN << std::vector<unsigned char>({75});
|
||||||
BOOST_CHECK(!ExtractDestination(s, address));
|
BOOST_CHECK(!ExtractDestination(s, address));
|
||||||
|
|
||||||
// TX_WITNESS_V0_KEYHASH
|
// TxoutType::WITNESS_V0_KEYHASH
|
||||||
s.clear();
|
s.clear();
|
||||||
s << OP_0 << ToByteVector(pubkey.GetID());
|
s << OP_0 << ToByteVector(pubkey.GetID());
|
||||||
BOOST_CHECK(ExtractDestination(s, address));
|
BOOST_CHECK(ExtractDestination(s, address));
|
||||||
|
@ -219,7 +219,7 @@ BOOST_AUTO_TEST_CASE(script_standard_ExtractDestination)
|
||||||
CHash160().Write(pubkey.begin(), pubkey.size()).Finalize(keyhash.begin());
|
CHash160().Write(pubkey.begin(), pubkey.size()).Finalize(keyhash.begin());
|
||||||
BOOST_CHECK(boost::get<WitnessV0KeyHash>(&address) && *boost::get<WitnessV0KeyHash>(&address) == keyhash);
|
BOOST_CHECK(boost::get<WitnessV0KeyHash>(&address) && *boost::get<WitnessV0KeyHash>(&address) == keyhash);
|
||||||
|
|
||||||
// TX_WITNESS_V0_SCRIPTHASH
|
// TxoutType::WITNESS_V0_SCRIPTHASH
|
||||||
s.clear();
|
s.clear();
|
||||||
WitnessV0ScriptHash scripthash;
|
WitnessV0ScriptHash scripthash;
|
||||||
CSHA256().Write(redeemScript.data(), redeemScript.size()).Finalize(scripthash.begin());
|
CSHA256().Write(redeemScript.data(), redeemScript.size()).Finalize(scripthash.begin());
|
||||||
|
@ -227,7 +227,7 @@ BOOST_AUTO_TEST_CASE(script_standard_ExtractDestination)
|
||||||
BOOST_CHECK(ExtractDestination(s, address));
|
BOOST_CHECK(ExtractDestination(s, address));
|
||||||
BOOST_CHECK(boost::get<WitnessV0ScriptHash>(&address) && *boost::get<WitnessV0ScriptHash>(&address) == scripthash);
|
BOOST_CHECK(boost::get<WitnessV0ScriptHash>(&address) && *boost::get<WitnessV0ScriptHash>(&address) == scripthash);
|
||||||
|
|
||||||
// TX_WITNESS_UNKNOWN with unknown version
|
// TxoutType::WITNESS_UNKNOWN with unknown version
|
||||||
s.clear();
|
s.clear();
|
||||||
s << OP_1 << ToByteVector(pubkey);
|
s << OP_1 << ToByteVector(pubkey);
|
||||||
BOOST_CHECK(ExtractDestination(s, address));
|
BOOST_CHECK(ExtractDestination(s, address));
|
||||||
|
@ -248,49 +248,49 @@ BOOST_AUTO_TEST_CASE(script_standard_ExtractDestinations)
|
||||||
}
|
}
|
||||||
|
|
||||||
CScript s;
|
CScript s;
|
||||||
txnouttype whichType;
|
TxoutType whichType;
|
||||||
std::vector<CTxDestination> addresses;
|
std::vector<CTxDestination> addresses;
|
||||||
int nRequired;
|
int nRequired;
|
||||||
|
|
||||||
// TX_PUBKEY
|
// TxoutType::PUBKEY
|
||||||
s.clear();
|
s.clear();
|
||||||
s << ToByteVector(pubkeys[0]) << OP_CHECKSIG;
|
s << ToByteVector(pubkeys[0]) << OP_CHECKSIG;
|
||||||
BOOST_CHECK(ExtractDestinations(s, whichType, addresses, nRequired));
|
BOOST_CHECK(ExtractDestinations(s, whichType, addresses, nRequired));
|
||||||
BOOST_CHECK_EQUAL(whichType, TX_PUBKEY);
|
BOOST_CHECK_EQUAL(whichType, TxoutType::PUBKEY);
|
||||||
BOOST_CHECK_EQUAL(addresses.size(), 1U);
|
BOOST_CHECK_EQUAL(addresses.size(), 1U);
|
||||||
BOOST_CHECK_EQUAL(nRequired, 1);
|
BOOST_CHECK_EQUAL(nRequired, 1);
|
||||||
BOOST_CHECK(boost::get<PKHash>(&addresses[0]) &&
|
BOOST_CHECK(boost::get<PKHash>(&addresses[0]) &&
|
||||||
*boost::get<PKHash>(&addresses[0]) == PKHash(pubkeys[0]));
|
*boost::get<PKHash>(&addresses[0]) == PKHash(pubkeys[0]));
|
||||||
|
|
||||||
// TX_PUBKEYHASH
|
// TxoutType::PUBKEYHASH
|
||||||
s.clear();
|
s.clear();
|
||||||
s << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
|
s << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
|
||||||
BOOST_CHECK(ExtractDestinations(s, whichType, addresses, nRequired));
|
BOOST_CHECK(ExtractDestinations(s, whichType, addresses, nRequired));
|
||||||
BOOST_CHECK_EQUAL(whichType, TX_PUBKEYHASH);
|
BOOST_CHECK_EQUAL(whichType, TxoutType::PUBKEYHASH);
|
||||||
BOOST_CHECK_EQUAL(addresses.size(), 1U);
|
BOOST_CHECK_EQUAL(addresses.size(), 1U);
|
||||||
BOOST_CHECK_EQUAL(nRequired, 1);
|
BOOST_CHECK_EQUAL(nRequired, 1);
|
||||||
BOOST_CHECK(boost::get<PKHash>(&addresses[0]) &&
|
BOOST_CHECK(boost::get<PKHash>(&addresses[0]) &&
|
||||||
*boost::get<PKHash>(&addresses[0]) == PKHash(pubkeys[0]));
|
*boost::get<PKHash>(&addresses[0]) == PKHash(pubkeys[0]));
|
||||||
|
|
||||||
// TX_SCRIPTHASH
|
// TxoutType::SCRIPTHASH
|
||||||
CScript redeemScript(s); // initialize with leftover P2PKH script
|
CScript redeemScript(s); // initialize with leftover P2PKH script
|
||||||
s.clear();
|
s.clear();
|
||||||
s << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
|
s << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
|
||||||
BOOST_CHECK(ExtractDestinations(s, whichType, addresses, nRequired));
|
BOOST_CHECK(ExtractDestinations(s, whichType, addresses, nRequired));
|
||||||
BOOST_CHECK_EQUAL(whichType, TX_SCRIPTHASH);
|
BOOST_CHECK_EQUAL(whichType, TxoutType::SCRIPTHASH);
|
||||||
BOOST_CHECK_EQUAL(addresses.size(), 1U);
|
BOOST_CHECK_EQUAL(addresses.size(), 1U);
|
||||||
BOOST_CHECK_EQUAL(nRequired, 1);
|
BOOST_CHECK_EQUAL(nRequired, 1);
|
||||||
BOOST_CHECK(boost::get<ScriptHash>(&addresses[0]) &&
|
BOOST_CHECK(boost::get<ScriptHash>(&addresses[0]) &&
|
||||||
*boost::get<ScriptHash>(&addresses[0]) == ScriptHash(redeemScript));
|
*boost::get<ScriptHash>(&addresses[0]) == ScriptHash(redeemScript));
|
||||||
|
|
||||||
// TX_MULTISIG
|
// TxoutType::MULTISIG
|
||||||
s.clear();
|
s.clear();
|
||||||
s << OP_2 <<
|
s << OP_2 <<
|
||||||
ToByteVector(pubkeys[0]) <<
|
ToByteVector(pubkeys[0]) <<
|
||||||
ToByteVector(pubkeys[1]) <<
|
ToByteVector(pubkeys[1]) <<
|
||||||
OP_2 << OP_CHECKMULTISIG;
|
OP_2 << OP_CHECKMULTISIG;
|
||||||
BOOST_CHECK(ExtractDestinations(s, whichType, addresses, nRequired));
|
BOOST_CHECK(ExtractDestinations(s, whichType, addresses, nRequired));
|
||||||
BOOST_CHECK_EQUAL(whichType, TX_MULTISIG);
|
BOOST_CHECK_EQUAL(whichType, TxoutType::MULTISIG);
|
||||||
BOOST_CHECK_EQUAL(addresses.size(), 2U);
|
BOOST_CHECK_EQUAL(addresses.size(), 2U);
|
||||||
BOOST_CHECK_EQUAL(nRequired, 2);
|
BOOST_CHECK_EQUAL(nRequired, 2);
|
||||||
BOOST_CHECK(boost::get<PKHash>(&addresses[0]) &&
|
BOOST_CHECK(boost::get<PKHash>(&addresses[0]) &&
|
||||||
|
@ -298,7 +298,7 @@ BOOST_AUTO_TEST_CASE(script_standard_ExtractDestinations)
|
||||||
BOOST_CHECK(boost::get<PKHash>(&addresses[1]) &&
|
BOOST_CHECK(boost::get<PKHash>(&addresses[1]) &&
|
||||||
*boost::get<PKHash>(&addresses[1]) == PKHash(pubkeys[1]));
|
*boost::get<PKHash>(&addresses[1]) == PKHash(pubkeys[1]));
|
||||||
|
|
||||||
// TX_NULL_DATA
|
// TxoutType::NULL_DATA
|
||||||
s.clear();
|
s.clear();
|
||||||
s << OP_RETURN << std::vector<unsigned char>({75});
|
s << OP_RETURN << std::vector<unsigned char>({75});
|
||||||
BOOST_CHECK(!ExtractDestinations(s, whichType, addresses, nRequired));
|
BOOST_CHECK(!ExtractDestinations(s, whichType, addresses, nRequired));
|
||||||
|
|
|
@ -716,12 +716,12 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
|
||||||
BOOST_CHECK(!IsStandardTx(CTransaction(t), reason));
|
BOOST_CHECK(!IsStandardTx(CTransaction(t), reason));
|
||||||
BOOST_CHECK_EQUAL(reason, "scriptpubkey");
|
BOOST_CHECK_EQUAL(reason, "scriptpubkey");
|
||||||
|
|
||||||
// MAX_OP_RETURN_RELAY-byte TX_NULL_DATA (standard)
|
// MAX_OP_RETURN_RELAY-byte TxoutType::NULL_DATA (standard)
|
||||||
t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38");
|
t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38");
|
||||||
BOOST_CHECK_EQUAL(MAX_OP_RETURN_RELAY, t.vout[0].scriptPubKey.size());
|
BOOST_CHECK_EQUAL(MAX_OP_RETURN_RELAY, t.vout[0].scriptPubKey.size());
|
||||||
BOOST_CHECK(IsStandardTx(CTransaction(t), reason));
|
BOOST_CHECK(IsStandardTx(CTransaction(t), reason));
|
||||||
|
|
||||||
// MAX_OP_RETURN_RELAY+1-byte TX_NULL_DATA (non-standard)
|
// MAX_OP_RETURN_RELAY+1-byte TxoutType::NULL_DATA (non-standard)
|
||||||
t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3800");
|
t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3800");
|
||||||
BOOST_CHECK_EQUAL(MAX_OP_RETURN_RELAY + 1, t.vout[0].scriptPubKey.size());
|
BOOST_CHECK_EQUAL(MAX_OP_RETURN_RELAY + 1, t.vout[0].scriptPubKey.size());
|
||||||
reason.clear();
|
reason.clear();
|
||||||
|
@ -745,12 +745,12 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
|
||||||
BOOST_CHECK(!IsStandardTx(CTransaction(t), reason));
|
BOOST_CHECK(!IsStandardTx(CTransaction(t), reason));
|
||||||
BOOST_CHECK_EQUAL(reason, "scriptpubkey");
|
BOOST_CHECK_EQUAL(reason, "scriptpubkey");
|
||||||
|
|
||||||
// TX_NULL_DATA w/o PUSHDATA
|
// TxoutType::NULL_DATA w/o PUSHDATA
|
||||||
t.vout.resize(1);
|
t.vout.resize(1);
|
||||||
t.vout[0].scriptPubKey = CScript() << OP_RETURN;
|
t.vout[0].scriptPubKey = CScript() << OP_RETURN;
|
||||||
BOOST_CHECK(IsStandardTx(CTransaction(t), reason));
|
BOOST_CHECK(IsStandardTx(CTransaction(t), reason));
|
||||||
|
|
||||||
// Only one TX_NULL_DATA permitted in all cases
|
// Only one TxoutType::NULL_DATA permitted in all cases
|
||||||
t.vout.resize(2);
|
t.vout.resize(2);
|
||||||
t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38");
|
t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38");
|
||||||
t.vout[1].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38");
|
t.vout[1].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38");
|
||||||
|
|
|
@ -22,8 +22,8 @@ CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey, int n
|
||||||
CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CScriptWitness& scriptWitness, const CTransaction& txCredit);
|
CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CScriptWitness& scriptWitness, const CTransaction& txCredit);
|
||||||
|
|
||||||
// Helper: create two dummy transactions, each with two outputs.
|
// Helper: create two dummy transactions, each with two outputs.
|
||||||
// The first has nValues[0] and nValues[1] outputs paid to a TX_PUBKEY,
|
// The first has nValues[0] and nValues[1] outputs paid to a TxoutType::PUBKEY,
|
||||||
// the second nValues[2] and nValues[3] outputs paid to a TX_PUBKEYHASH.
|
// the second nValues[2] and nValues[3] outputs paid to a TxoutType::PUBKEYHASH.
|
||||||
std::vector<CMutableTransaction> SetupDummyInputs(FillableSigningProvider& keystoreRet, CCoinsViewCache& coinsRet, const std::array<CAmount,4>& nValues);
|
std::vector<CMutableTransaction> SetupDummyInputs(FillableSigningProvider& keystoreRet, CCoinsViewCache& coinsRet, const std::array<CAmount,4>& nValues);
|
||||||
|
|
||||||
#endif // BITCOIN_TEST_UTIL_TRANSACTION_UTILS_H
|
#endif // BITCOIN_TEST_UTIL_TRANSACTION_UTILS_H
|
||||||
|
|
|
@ -856,20 +856,20 @@ static std::string RecurseImportData(const CScript& script, ImportData& import_d
|
||||||
{
|
{
|
||||||
// Use Solver to obtain script type and parsed pubkeys or hashes:
|
// Use Solver to obtain script type and parsed pubkeys or hashes:
|
||||||
std::vector<std::vector<unsigned char>> solverdata;
|
std::vector<std::vector<unsigned char>> solverdata;
|
||||||
txnouttype script_type = Solver(script, solverdata);
|
TxoutType script_type = Solver(script, solverdata);
|
||||||
|
|
||||||
switch (script_type) {
|
switch (script_type) {
|
||||||
case TX_PUBKEY: {
|
case TxoutType::PUBKEY: {
|
||||||
CPubKey pubkey(solverdata[0].begin(), solverdata[0].end());
|
CPubKey pubkey(solverdata[0].begin(), solverdata[0].end());
|
||||||
import_data.used_keys.emplace(pubkey.GetID(), false);
|
import_data.used_keys.emplace(pubkey.GetID(), false);
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
case TX_PUBKEYHASH: {
|
case TxoutType::PUBKEYHASH: {
|
||||||
CKeyID id = CKeyID(uint160(solverdata[0]));
|
CKeyID id = CKeyID(uint160(solverdata[0]));
|
||||||
import_data.used_keys[id] = true;
|
import_data.used_keys[id] = true;
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
case TX_SCRIPTHASH: {
|
case TxoutType::SCRIPTHASH: {
|
||||||
if (script_ctx == ScriptContext::P2SH) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Trying to nest P2SH inside another P2SH");
|
if (script_ctx == ScriptContext::P2SH) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Trying to nest P2SH inside another P2SH");
|
||||||
if (script_ctx == ScriptContext::WITNESS_V0) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Trying to nest P2SH inside a P2WSH");
|
if (script_ctx == ScriptContext::WITNESS_V0) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Trying to nest P2SH inside a P2WSH");
|
||||||
CHECK_NONFATAL(script_ctx == ScriptContext::TOP);
|
CHECK_NONFATAL(script_ctx == ScriptContext::TOP);
|
||||||
|
@ -880,14 +880,14 @@ static std::string RecurseImportData(const CScript& script, ImportData& import_d
|
||||||
import_data.import_scripts.emplace(*subscript);
|
import_data.import_scripts.emplace(*subscript);
|
||||||
return RecurseImportData(*subscript, import_data, ScriptContext::P2SH);
|
return RecurseImportData(*subscript, import_data, ScriptContext::P2SH);
|
||||||
}
|
}
|
||||||
case TX_MULTISIG: {
|
case TxoutType::MULTISIG: {
|
||||||
for (size_t i = 1; i + 1< solverdata.size(); ++i) {
|
for (size_t i = 1; i + 1< solverdata.size(); ++i) {
|
||||||
CPubKey pubkey(solverdata[i].begin(), solverdata[i].end());
|
CPubKey pubkey(solverdata[i].begin(), solverdata[i].end());
|
||||||
import_data.used_keys.emplace(pubkey.GetID(), false);
|
import_data.used_keys.emplace(pubkey.GetID(), false);
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
case TX_WITNESS_V0_SCRIPTHASH: {
|
case TxoutType::WITNESS_V0_SCRIPTHASH: {
|
||||||
if (script_ctx == ScriptContext::WITNESS_V0) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Trying to nest P2WSH inside another P2WSH");
|
if (script_ctx == ScriptContext::WITNESS_V0) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Trying to nest P2WSH inside another P2WSH");
|
||||||
uint256 fullid(solverdata[0]);
|
uint256 fullid(solverdata[0]);
|
||||||
CScriptID id;
|
CScriptID id;
|
||||||
|
@ -901,7 +901,7 @@ static std::string RecurseImportData(const CScript& script, ImportData& import_d
|
||||||
import_data.import_scripts.emplace(*subscript);
|
import_data.import_scripts.emplace(*subscript);
|
||||||
return RecurseImportData(*subscript, import_data, ScriptContext::WITNESS_V0);
|
return RecurseImportData(*subscript, import_data, ScriptContext::WITNESS_V0);
|
||||||
}
|
}
|
||||||
case TX_WITNESS_V0_KEYHASH: {
|
case TxoutType::WITNESS_V0_KEYHASH: {
|
||||||
if (script_ctx == ScriptContext::WITNESS_V0) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Trying to nest P2WPKH inside P2WSH");
|
if (script_ctx == ScriptContext::WITNESS_V0) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Trying to nest P2WPKH inside P2WSH");
|
||||||
CKeyID id = CKeyID(uint160(solverdata[0]));
|
CKeyID id = CKeyID(uint160(solverdata[0]));
|
||||||
import_data.used_keys[id] = true;
|
import_data.used_keys[id] = true;
|
||||||
|
@ -910,10 +910,10 @@ static std::string RecurseImportData(const CScript& script, ImportData& import_d
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
case TX_NULL_DATA:
|
case TxoutType::NULL_DATA:
|
||||||
return "unspendable script";
|
return "unspendable script";
|
||||||
case TX_NONSTANDARD:
|
case TxoutType::NONSTANDARD:
|
||||||
case TX_WITNESS_UNKNOWN:
|
case TxoutType::WITNESS_UNKNOWN:
|
||||||
default:
|
default:
|
||||||
return "unrecognized script";
|
return "unrecognized script";
|
||||||
}
|
}
|
||||||
|
|
|
@ -3489,7 +3489,7 @@ public:
|
||||||
{
|
{
|
||||||
// Always present: script type and redeemscript
|
// Always present: script type and redeemscript
|
||||||
std::vector<std::vector<unsigned char>> solutions_data;
|
std::vector<std::vector<unsigned char>> solutions_data;
|
||||||
txnouttype which_type = Solver(subscript, solutions_data);
|
TxoutType which_type = Solver(subscript, solutions_data);
|
||||||
obj.pushKV("script", GetTxnOutputType(which_type));
|
obj.pushKV("script", GetTxnOutputType(which_type));
|
||||||
obj.pushKV("hex", HexStr(subscript.begin(), subscript.end()));
|
obj.pushKV("hex", HexStr(subscript.begin(), subscript.end()));
|
||||||
|
|
||||||
|
@ -3506,7 +3506,7 @@ public:
|
||||||
// Always report the pubkey at the top level, so that `getnewaddress()['pubkey']` always works.
|
// Always report the pubkey at the top level, so that `getnewaddress()['pubkey']` always works.
|
||||||
if (subobj.exists("pubkey")) obj.pushKV("pubkey", subobj["pubkey"]);
|
if (subobj.exists("pubkey")) obj.pushKV("pubkey", subobj["pubkey"]);
|
||||||
obj.pushKV("embedded", std::move(subobj));
|
obj.pushKV("embedded", std::move(subobj));
|
||||||
} else if (which_type == TX_MULTISIG) {
|
} else if (which_type == TxoutType::MULTISIG) {
|
||||||
// Also report some information on multisig scripts (which do not have a corresponding address).
|
// Also report some information on multisig scripts (which do not have a corresponding address).
|
||||||
// TODO: abstract out the common functionality between this logic and ExtractDestinations.
|
// TODO: abstract out the common functionality between this logic and ExtractDestinations.
|
||||||
obj.pushKV("sigsrequired", solutions_data[0][0]);
|
obj.pushKV("sigsrequired", solutions_data[0][0]);
|
||||||
|
|
|
@ -88,16 +88,16 @@ IsMineResult IsMineInner(const LegacyScriptPubKeyMan& keystore, const CScript& s
|
||||||
IsMineResult ret = IsMineResult::NO;
|
IsMineResult ret = IsMineResult::NO;
|
||||||
|
|
||||||
std::vector<valtype> vSolutions;
|
std::vector<valtype> vSolutions;
|
||||||
txnouttype whichType = Solver(scriptPubKey, vSolutions);
|
TxoutType whichType = Solver(scriptPubKey, vSolutions);
|
||||||
|
|
||||||
CKeyID keyID;
|
CKeyID keyID;
|
||||||
switch (whichType)
|
switch (whichType)
|
||||||
{
|
{
|
||||||
case TX_NONSTANDARD:
|
case TxoutType::NONSTANDARD:
|
||||||
case TX_NULL_DATA:
|
case TxoutType::NULL_DATA:
|
||||||
case TX_WITNESS_UNKNOWN:
|
case TxoutType::WITNESS_UNKNOWN:
|
||||||
break;
|
break;
|
||||||
case TX_PUBKEY:
|
case TxoutType::PUBKEY:
|
||||||
keyID = CPubKey(vSolutions[0]).GetID();
|
keyID = CPubKey(vSolutions[0]).GetID();
|
||||||
if (!PermitsUncompressed(sigversion) && vSolutions[0].size() != 33) {
|
if (!PermitsUncompressed(sigversion) && vSolutions[0].size() != 33) {
|
||||||
return IsMineResult::INVALID;
|
return IsMineResult::INVALID;
|
||||||
|
@ -106,7 +106,7 @@ IsMineResult IsMineInner(const LegacyScriptPubKeyMan& keystore, const CScript& s
|
||||||
ret = std::max(ret, IsMineResult::SPENDABLE);
|
ret = std::max(ret, IsMineResult::SPENDABLE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TX_WITNESS_V0_KEYHASH:
|
case TxoutType::WITNESS_V0_KEYHASH:
|
||||||
{
|
{
|
||||||
if (sigversion == IsMineSigVersion::WITNESS_V0) {
|
if (sigversion == IsMineSigVersion::WITNESS_V0) {
|
||||||
// P2WPKH inside P2WSH is invalid.
|
// P2WPKH inside P2WSH is invalid.
|
||||||
|
@ -121,7 +121,7 @@ IsMineResult IsMineInner(const LegacyScriptPubKeyMan& keystore, const CScript& s
|
||||||
ret = std::max(ret, IsMineInner(keystore, GetScriptForDestination(PKHash(uint160(vSolutions[0]))), IsMineSigVersion::WITNESS_V0));
|
ret = std::max(ret, IsMineInner(keystore, GetScriptForDestination(PKHash(uint160(vSolutions[0]))), IsMineSigVersion::WITNESS_V0));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TX_PUBKEYHASH:
|
case TxoutType::PUBKEYHASH:
|
||||||
keyID = CKeyID(uint160(vSolutions[0]));
|
keyID = CKeyID(uint160(vSolutions[0]));
|
||||||
if (!PermitsUncompressed(sigversion)) {
|
if (!PermitsUncompressed(sigversion)) {
|
||||||
CPubKey pubkey;
|
CPubKey pubkey;
|
||||||
|
@ -133,7 +133,7 @@ IsMineResult IsMineInner(const LegacyScriptPubKeyMan& keystore, const CScript& s
|
||||||
ret = std::max(ret, IsMineResult::SPENDABLE);
|
ret = std::max(ret, IsMineResult::SPENDABLE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TX_SCRIPTHASH:
|
case TxoutType::SCRIPTHASH:
|
||||||
{
|
{
|
||||||
if (sigversion != IsMineSigVersion::TOP) {
|
if (sigversion != IsMineSigVersion::TOP) {
|
||||||
// P2SH inside P2WSH or P2SH is invalid.
|
// P2SH inside P2WSH or P2SH is invalid.
|
||||||
|
@ -146,7 +146,7 @@ IsMineResult IsMineInner(const LegacyScriptPubKeyMan& keystore, const CScript& s
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TX_WITNESS_V0_SCRIPTHASH:
|
case TxoutType::WITNESS_V0_SCRIPTHASH:
|
||||||
{
|
{
|
||||||
if (sigversion == IsMineSigVersion::WITNESS_V0) {
|
if (sigversion == IsMineSigVersion::WITNESS_V0) {
|
||||||
// P2WSH inside P2WSH is invalid.
|
// P2WSH inside P2WSH is invalid.
|
||||||
|
@ -165,7 +165,7 @@ IsMineResult IsMineInner(const LegacyScriptPubKeyMan& keystore, const CScript& s
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case TX_MULTISIG:
|
case TxoutType::MULTISIG:
|
||||||
{
|
{
|
||||||
// Never treat bare multisig outputs as ours (they can still be made watchonly-though)
|
// Never treat bare multisig outputs as ours (they can still be made watchonly-though)
|
||||||
if (sigversion == IsMineSigVersion::TOP) {
|
if (sigversion == IsMineSigVersion::TOP) {
|
||||||
|
@ -825,7 +825,7 @@ bool LegacyScriptPubKeyMan::HaveWatchOnly() const
|
||||||
static bool ExtractPubKey(const CScript &dest, CPubKey& pubKeyOut)
|
static bool ExtractPubKey(const CScript &dest, CPubKey& pubKeyOut)
|
||||||
{
|
{
|
||||||
std::vector<std::vector<unsigned char>> solutions;
|
std::vector<std::vector<unsigned char>> solutions;
|
||||||
return Solver(dest, solutions) == TX_PUBKEY &&
|
return Solver(dest, solutions) == TxoutType::PUBKEY &&
|
||||||
(pubKeyOut = CPubKey(solutions[0])).IsFullyValid();
|
(pubKeyOut = CPubKey(solutions[0])).IsFullyValid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue