Changeset View
Changeset View
Standalone View
Standalone View
src/script/standard.cpp
Show First 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | static bool MatchMultisig(const CScript &script, unsigned int &required, | ||||
} | } | ||||
unsigned int keys = CScript::DecodeOP_N(opcode); | unsigned int keys = CScript::DecodeOP_N(opcode); | ||||
if (pubkeys.size() != keys || keys < required) { | if (pubkeys.size() != keys || keys < required) { | ||||
return false; | return false; | ||||
} | } | ||||
return (it + 1 == script.end()); | return (it + 1 == script.end()); | ||||
} | } | ||||
bool Solver(const CScript &scriptPubKey, txnouttype &typeRet, | txnouttype Solver(const CScript &scriptPubKey, | ||||
std::vector<std::vector<uint8_t>> &vSolutionsRet) { | std::vector<std::vector<uint8_t>> &vSolutionsRet) { | ||||
vSolutionsRet.clear(); | vSolutionsRet.clear(); | ||||
// Shortcut for pay-to-script-hash, which are more constrained than the | // Shortcut for pay-to-script-hash, which are more constrained than the | ||||
// other types: | // other types: | ||||
// it is always OP_HASH160 20 [20 byte hash] OP_EQUAL | // it is always OP_HASH160 20 [20 byte hash] OP_EQUAL | ||||
if (scriptPubKey.IsPayToScriptHash()) { | if (scriptPubKey.IsPayToScriptHash()) { | ||||
typeRet = TX_SCRIPTHASH; | |||||
std::vector<uint8_t> hashBytes(scriptPubKey.begin() + 2, | std::vector<uint8_t> hashBytes(scriptPubKey.begin() + 2, | ||||
scriptPubKey.begin() + 22); | scriptPubKey.begin() + 22); | ||||
vSolutionsRet.push_back(hashBytes); | vSolutionsRet.push_back(hashBytes); | ||||
return true; | return TX_SCRIPTHASH; | ||||
} | } | ||||
// Provably prunable, data-carrying output | // Provably prunable, data-carrying output | ||||
// | // | ||||
// So long as script passes the IsUnspendable() test and all but the first | // So long as script passes the IsUnspendable() test and all but the first | ||||
// 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 && | if (scriptPubKey.size() >= 1 && scriptPubKey[0] == OP_RETURN && | ||||
scriptPubKey.IsPushOnly(scriptPubKey.begin() + 1)) { | scriptPubKey.IsPushOnly(scriptPubKey.begin() + 1)) { | ||||
typeRet = TX_NULL_DATA; | return TX_NULL_DATA; | ||||
return true; | |||||
} | } | ||||
std::vector<uint8_t> data; | std::vector<uint8_t> data; | ||||
if (MatchPayToPubkey(scriptPubKey, data)) { | if (MatchPayToPubkey(scriptPubKey, data)) { | ||||
typeRet = TX_PUBKEY; | |||||
vSolutionsRet.push_back(std::move(data)); | vSolutionsRet.push_back(std::move(data)); | ||||
return true; | return TX_PUBKEY; | ||||
} | } | ||||
if (MatchPayToPubkeyHash(scriptPubKey, data)) { | if (MatchPayToPubkeyHash(scriptPubKey, data)) { | ||||
typeRet = TX_PUBKEYHASH; | |||||
vSolutionsRet.push_back(std::move(data)); | vSolutionsRet.push_back(std::move(data)); | ||||
return true; | return TX_PUBKEYHASH; | ||||
} | } | ||||
unsigned int required; | unsigned int required; | ||||
std::vector<std::vector<uint8_t>> keys; | std::vector<std::vector<uint8_t>> keys; | ||||
if (MatchMultisig(scriptPubKey, required, keys)) { | if (MatchMultisig(scriptPubKey, required, keys)) { | ||||
typeRet = TX_MULTISIG; | |||||
// safe as required is in range 1..16 | // safe as required is in range 1..16 | ||||
vSolutionsRet.push_back({static_cast<uint8_t>(required)}); | vSolutionsRet.push_back({static_cast<uint8_t>(required)}); | ||||
vSolutionsRet.insert(vSolutionsRet.end(), keys.begin(), keys.end()); | vSolutionsRet.insert(vSolutionsRet.end(), keys.begin(), keys.end()); | ||||
// safe as size is in range 1..16 | // safe as size is in range 1..16 | ||||
vSolutionsRet.push_back({static_cast<uint8_t>(keys.size())}); | vSolutionsRet.push_back({static_cast<uint8_t>(keys.size())}); | ||||
return true; | return TX_MULTISIG; | ||||
} | } | ||||
vSolutionsRet.clear(); | vSolutionsRet.clear(); | ||||
typeRet = TX_NONSTANDARD; | return TX_NONSTANDARD; | ||||
return false; | |||||
} | } | ||||
bool ExtractDestination(const CScript &scriptPubKey, | bool ExtractDestination(const CScript &scriptPubKey, | ||||
CTxDestination &addressRet) { | CTxDestination &addressRet) { | ||||
std::vector<valtype> vSolutions; | std::vector<valtype> vSolutions; | ||||
txnouttype whichType; | txnouttype whichType = Solver(scriptPubKey, vSolutions); | ||||
if (!Solver(scriptPubKey, whichType, vSolutions)) { | |||||
return false; | |||||
} | |||||
if (whichType == TX_PUBKEY) { | if (whichType == TX_PUBKEY) { | ||||
CPubKey pubKey(vSolutions[0]); | CPubKey pubKey(vSolutions[0]); | ||||
if (!pubKey.IsValid()) { | if (!pubKey.IsValid()) { | ||||
return false; | return false; | ||||
} | } | ||||
addressRet = pubKey.GetID(); | addressRet = pubKey.GetID(); | ||||
Show All 10 Lines | bool ExtractDestination(const CScript &scriptPubKey, | ||||
// Multisig txns have more than one address... | // Multisig txns have more than one address... | ||||
return false; | return false; | ||||
} | } | ||||
bool ExtractDestinations(const CScript &scriptPubKey, txnouttype &typeRet, | bool ExtractDestinations(const CScript &scriptPubKey, txnouttype &typeRet, | ||||
std::vector<CTxDestination> &addressRet, | std::vector<CTxDestination> &addressRet, | ||||
int &nRequiredRet) { | int &nRequiredRet) { | ||||
addressRet.clear(); | addressRet.clear(); | ||||
typeRet = TX_NONSTANDARD; | |||||
std::vector<valtype> vSolutions; | std::vector<valtype> vSolutions; | ||||
if (!Solver(scriptPubKey, typeRet, vSolutions)) { | typeRet = Solver(scriptPubKey, vSolutions); | ||||
if (typeRet == TX_NONSTANDARD) { | |||||
return false; | return false; | ||||
} | } else if (typeRet == TX_NULL_DATA) { | ||||
if (typeRet == TX_NULL_DATA) { | |||||
// This is data, not addresses | // This is data, not addresses | ||||
return false; | return false; | ||||
} | } | ||||
if (typeRet == TX_MULTISIG) { | if (typeRet == TX_MULTISIG) { | ||||
nRequiredRet = vSolutions.front()[0]; | nRequiredRet = vSolutions.front()[0]; | ||||
for (size_t i = 1; i < vSolutions.size() - 1; i++) { | for (size_t i = 1; i < vSolutions.size() - 1; i++) { | ||||
CPubKey pubKey(vSolutions[i]); | CPubKey pubKey(vSolutions[i]); | ||||
▲ Show 20 Lines • Show All 77 Lines • Show Last 20 Lines |