Changeset View
Changeset View
Standalone View
Standalone View
src/script/standard.cpp
Show First 20 Lines • Show All 101 Lines • ▼ Show 20 Lines | for (const std::pair<txnouttype, CScript> &tplate : mTemplates) { | ||||
if (pc1 == script1.end() && pc2 == script2.end()) { | if (pc1 == script1.end() && pc2 == script2.end()) { | ||||
// Found a match | // Found a match | ||||
typeRet = tplate.first; | typeRet = tplate.first; | ||||
if (typeRet == TX_MULTISIG) { | if (typeRet == TX_MULTISIG) { | ||||
// Additional checks for TX_MULTISIG: | // Additional checks for TX_MULTISIG: | ||||
uint8_t m = vSolutionsRet.front()[0]; | uint8_t m = vSolutionsRet.front()[0]; | ||||
uint8_t n = vSolutionsRet.back()[0]; | uint8_t n = vSolutionsRet.back()[0]; | ||||
if (m < 1 || n < 1 || m > n || | if (m < 1 || n < 1 || m > n || | ||||
vSolutionsRet.size() - 2 != n) | vSolutionsRet.size() - 2 != n) { | ||||
return false; | return false; | ||||
} | } | ||||
} | |||||
return true; | return true; | ||||
} | } | ||||
if (!script1.GetOp(pc1, opcode1, vch1)) break; | if (!script1.GetOp(pc1, opcode1, vch1)) { | ||||
if (!script2.GetOp(pc2, opcode2, vch2)) break; | break; | ||||
} | |||||
if (!script2.GetOp(pc2, opcode2, vch2)) { | |||||
break; | |||||
} | |||||
// Template matching opcodes: | // Template matching opcodes: | ||||
if (opcode2 == OP_PUBKEYS) { | if (opcode2 == OP_PUBKEYS) { | ||||
while (vch1.size() >= 33 && vch1.size() <= 65) { | while (vch1.size() >= 33 && vch1.size() <= 65) { | ||||
vSolutionsRet.push_back(vch1); | vSolutionsRet.push_back(vch1); | ||||
if (!script1.GetOp(pc1, opcode1, vch1)) break; | if (!script1.GetOp(pc1, opcode1, vch1)) { | ||||
break; | |||||
} | |||||
} | |||||
if (!script2.GetOp(pc2, opcode2, vch2)) { | |||||
break; | |||||
} | } | ||||
if (!script2.GetOp(pc2, opcode2, vch2)) break; | |||||
// Normal situation is to fall through to other if/else | // Normal situation is to fall through to other if/else | ||||
// statements | // statements | ||||
} | } | ||||
if (opcode2 == OP_PUBKEY) { | if (opcode2 == OP_PUBKEY) { | ||||
if (vch1.size() < 33 || vch1.size() > 65) break; | if (vch1.size() < 33 || vch1.size() > 65) { | ||||
break; | |||||
} | |||||
vSolutionsRet.push_back(vch1); | vSolutionsRet.push_back(vch1); | ||||
} else if (opcode2 == OP_PUBKEYHASH) { | } else if (opcode2 == OP_PUBKEYHASH) { | ||||
if (vch1.size() != sizeof(uint160)) break; | if (vch1.size() != sizeof(uint160)) { | ||||
break; | |||||
} | |||||
vSolutionsRet.push_back(vch1); | vSolutionsRet.push_back(vch1); | ||||
} else if (opcode2 == OP_SMALLINTEGER) { | } else if (opcode2 == OP_SMALLINTEGER) { | ||||
// Single-byte small integer pushed onto vSolutions | // Single-byte small integer pushed onto vSolutions | ||||
if (opcode1 == OP_0 || (opcode1 >= OP_1 && opcode1 <= OP_16)) { | if (opcode1 == OP_0 || (opcode1 >= OP_1 && opcode1 <= OP_16)) { | ||||
char n = (char)CScript::DecodeOP_N(opcode1); | char n = (char)CScript::DecodeOP_N(opcode1); | ||||
vSolutionsRet.push_back(valtype(1, n)); | vSolutionsRet.push_back(valtype(1, n)); | ||||
} else | } else { | ||||
break; | break; | ||||
} | |||||
} else if (opcode1 != opcode2 || vch1 != vch2) { | } else if (opcode1 != opcode2 || vch1 != vch2) { | ||||
// Others must match exactly | // Others must match exactly | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
vSolutionsRet.clear(); | vSolutionsRet.clear(); | ||||
typeRet = TX_NONSTANDARD; | typeRet = TX_NONSTANDARD; | ||||
return false; | 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; | ||||
if (!Solver(scriptPubKey, whichType, vSolutions)) return false; | 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()) return false; | if (!pubKey.IsValid()) { | ||||
return false; | |||||
} | |||||
addressRet = pubKey.GetID(); | addressRet = pubKey.GetID(); | ||||
return true; | return true; | ||||
} else if (whichType == TX_PUBKEYHASH) { | } | ||||
if (whichType == TX_PUBKEYHASH) { | |||||
addressRet = CKeyID(uint160(vSolutions[0])); | addressRet = CKeyID(uint160(vSolutions[0])); | ||||
return true; | return true; | ||||
} else if (whichType == TX_SCRIPTHASH) { | } | ||||
if (whichType == TX_SCRIPTHASH) { | |||||
addressRet = CScriptID(uint160(vSolutions[0])); | addressRet = CScriptID(uint160(vSolutions[0])); | ||||
return true; | return true; | ||||
} | } | ||||
// 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; | typeRet = TX_NONSTANDARD; | ||||
std::vector<valtype> vSolutions; | std::vector<valtype> vSolutions; | ||||
if (!Solver(scriptPubKey, typeRet, vSolutions)) return false; | if (!Solver(scriptPubKey, typeRet, vSolutions)) { | ||||
return false; | |||||
} | |||||
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 (unsigned int 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]); | ||||
if (!pubKey.IsValid()) continue; | if (!pubKey.IsValid()) { | ||||
continue; | |||||
} | |||||
CTxDestination address = pubKey.GetID(); | CTxDestination address = pubKey.GetID(); | ||||
addressRet.push_back(address); | addressRet.push_back(address); | ||||
} | } | ||||
if (addressRet.empty()) return false; | if (addressRet.empty()) { | ||||
return false; | |||||
} | |||||
} else { | } else { | ||||
nRequiredRet = 1; | nRequiredRet = 1; | ||||
CTxDestination address; | CTxDestination address; | ||||
if (!ExtractDestination(scriptPubKey, address)) return false; | if (!ExtractDestination(scriptPubKey, address)) { | ||||
return false; | |||||
} | |||||
addressRet.push_back(address); | addressRet.push_back(address); | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
namespace { | namespace { | ||||
class CScriptVisitor : public boost::static_visitor<bool> { | class CScriptVisitor : public boost::static_visitor<bool> { | ||||
Show All 34 Lines | CScript GetScriptForRawPubKey(const CPubKey &pubKey) { | ||||
return CScript() << std::vector<uint8_t>(pubKey.begin(), pubKey.end()) | return CScript() << std::vector<uint8_t>(pubKey.begin(), pubKey.end()) | ||||
<< OP_CHECKSIG; | << OP_CHECKSIG; | ||||
} | } | ||||
CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey> &keys) { | CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey> &keys) { | ||||
CScript script; | CScript script; | ||||
script << CScript::EncodeOP_N(nRequired); | script << CScript::EncodeOP_N(nRequired); | ||||
for (const CPubKey &key : keys) | for (const CPubKey &key : keys) { | ||||
script << ToByteVector(key); | script << ToByteVector(key); | ||||
} | |||||
script << CScript::EncodeOP_N(keys.size()) << OP_CHECKMULTISIG; | script << CScript::EncodeOP_N(keys.size()) << OP_CHECKMULTISIG; | ||||
return script; | return script; | ||||
} | } | ||||
bool IsValidDestination(const CTxDestination &dest) { | bool IsValidDestination(const CTxDestination &dest) { | ||||
return dest.which() != 0; | return dest.which() != 0; | ||||
} | } |