Skip to content

Commit 4cef8e0

Browse files
committed
Merge #13429: Return the script type from Solver
984d72e Return the script type from Solver (Ben Woosley) Pull request description: Because false is synonymous with TX_NONSTANDARD, this conveys the same information and makes the handling explicitly based on script type, simplifying each call site. Prior to this change it was common for the return value to be ignored, or for the return value and TX_NONSTANDARD to be redundantly handled. Tree-SHA512: 31864f856b8cb75f4b782d12678070e8b1cfe9665c6f57cfb25e7ac8bcea8a22f9a78d7c8cf0101c841f2a612400666fb91798bffe88de856e98b873703b0965
2 parents 776fa60 + 984d72e commit 4cef8e0

File tree

10 files changed

+62
-98
lines changed

10 files changed

+62
-98
lines changed

src/bloom.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,11 +153,11 @@ bool CBloomFilter::IsRelevantAndUpdate(const CTransaction& tx)
153153
insert(COutPoint(hash, i));
154154
else if ((nFlags & BLOOM_UPDATE_MASK) == BLOOM_UPDATE_P2PUBKEY_ONLY)
155155
{
156-
txnouttype type;
157156
std::vector<std::vector<unsigned char> > vSolutions;
158-
if (Solver(txout.scriptPubKey, type, vSolutions) &&
159-
(type == TX_PUBKEY || type == TX_MULTISIG))
157+
txnouttype type = Solver(txout.scriptPubKey, vSolutions);
158+
if (type == TX_PUBKEY || type == TX_MULTISIG) {
160159
insert(COutPoint(hash, i));
160+
}
161161
}
162162
break;
163163
}

src/core_write.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,7 @@ void ScriptToUniv(const CScript& script, UniValue& out, bool include_address)
141141
out.pushKV("hex", HexStr(script.begin(), script.end()));
142142

143143
std::vector<std::vector<unsigned char>> solns;
144-
txnouttype type;
145-
Solver(script, type, solns);
144+
txnouttype type = Solver(script, solns);
146145
out.pushKV("type", GetTxnOutputType(type));
147146

148147
CTxDestination address;

src/policy/policy.cpp

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,11 @@ bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
5757
bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType)
5858
{
5959
std::vector<std::vector<unsigned char> > vSolutions;
60-
if (!Solver(scriptPubKey, whichType, vSolutions))
61-
return false;
60+
whichType = Solver(scriptPubKey, vSolutions);
6261

63-
if (whichType == TX_MULTISIG)
64-
{
62+
if (whichType == TX_NONSTANDARD || whichType == TX_WITNESS_UNKNOWN) {
63+
return false;
64+
} else if (whichType == TX_MULTISIG) {
6565
unsigned char m = vSolutions.front()[0];
6666
unsigned char n = vSolutions.back()[0];
6767
// Support up to x-of-3 multisig txns as standard
@@ -70,10 +70,11 @@ bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType)
7070
if (m < 1 || m > n)
7171
return false;
7272
} else if (whichType == TX_NULL_DATA &&
73-
(!fAcceptDatacarrier || scriptPubKey.size() > nMaxDatacarrierBytes))
73+
(!fAcceptDatacarrier || scriptPubKey.size() > nMaxDatacarrierBytes)) {
7474
return false;
75+
}
7576

76-
return whichType != TX_NONSTANDARD && whichType != TX_WITNESS_UNKNOWN;
77+
return true;
7778
}
7879

7980
bool IsStandardTx(const CTransaction& tx, std::string& reason)
@@ -166,14 +167,10 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
166167
const CTxOut& prev = mapInputs.AccessCoin(tx.vin[i].prevout).out;
167168

168169
std::vector<std::vector<unsigned char> > vSolutions;
169-
txnouttype whichType;
170-
// get the scriptPubKey corresponding to this input:
171-
const CScript& prevScript = prev.scriptPubKey;
172-
if (!Solver(prevScript, whichType, vSolutions))
170+
txnouttype whichType = Solver(prev.scriptPubKey, vSolutions);
171+
if (whichType == TX_NONSTANDARD) {
173172
return false;
174-
175-
if (whichType == TX_SCRIPTHASH)
176-
{
173+
} else if (whichType == TX_SCRIPTHASH) {
177174
std::vector<std::vector<unsigned char> > stack;
178175
// convert the scriptSig into a stack, so we can inspect the redeemScript
179176
if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), SigVersion::BASE))

src/rpc/rawtransaction.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -626,9 +626,8 @@ static UniValue decodescript(const JSONRPCRequest& request)
626626
// P2SH and witness programs cannot be wrapped in P2WSH, if this script
627627
// is a witness program, don't return addresses for a segwit programs.
628628
if (type.get_str() == "pubkey" || type.get_str() == "pubkeyhash" || type.get_str() == "multisig" || type.get_str() == "nonstandard") {
629-
txnouttype which_type;
630629
std::vector<std::vector<unsigned char>> solutions_data;
631-
Solver(script, which_type, solutions_data);
630+
txnouttype which_type = Solver(script, solutions_data);
632631
// Uncompressed pubkeys cannot be used with segwit checksigs.
633632
// If the script contains an uncompressed pubkey, skip encoding of a segwit program.
634633
if ((which_type == TX_PUBKEY) || (which_type == TX_MULTISIG)) {

src/script/ismine.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,7 @@ IsMineResult IsMineInner(const CKeyStore& keystore, const CScript& scriptPubKey,
6060
IsMineResult ret = IsMineResult::NO;
6161

6262
std::vector<valtype> vSolutions;
63-
txnouttype whichType;
64-
Solver(scriptPubKey, whichType, vSolutions);
63+
txnouttype whichType = Solver(scriptPubKey, vSolutions);
6564

6665
CKeyID keyID;
6766
switch (whichType)

src/script/sign.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,7 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
101101
std::vector<unsigned char> sig;
102102

103103
std::vector<valtype> vSolutions;
104-
if (!Solver(scriptPubKey, whichTypeRet, vSolutions))
105-
return false;
104+
whichTypeRet = Solver(scriptPubKey, vSolutions);
106105

107106
switch (whichTypeRet)
108107
{
@@ -329,9 +328,8 @@ SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nI
329328
}
330329

331330
// Get scripts
332-
txnouttype script_type;
333331
std::vector<std::vector<unsigned char>> solutions;
334-
Solver(txout.scriptPubKey, script_type, solutions);
332+
txnouttype script_type = Solver(txout.scriptPubKey, solutions);
335333
SigVersion sigversion = SigVersion::BASE;
336334
CScript next_script = txout.scriptPubKey;
337335

@@ -342,7 +340,7 @@ SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nI
342340
next_script = std::move(redeem_script);
343341

344342
// Get redeemScript type
345-
Solver(next_script, script_type, solutions);
343+
script_type = Solver(next_script, solutions);
346344
stack.script.pop_back();
347345
}
348346
if (script_type == TX_WITNESS_V0_SCRIPTHASH && !stack.witness.empty() && !stack.witness.back().empty()) {
@@ -352,7 +350,7 @@ SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nI
352350
next_script = std::move(witness_script);
353351

354352
// Get witnessScript type
355-
Solver(next_script, script_type, solutions);
353+
script_type = Solver(next_script, solutions);
356354
stack.witness.pop_back();
357355
stack.script = std::move(stack.witness);
358356
stack.witness.clear();

src/script/standard.cpp

Lines changed: 21 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -87,41 +87,36 @@ static bool MatchMultisig(const CScript& script, unsigned int& required, std::ve
8787
return (it + 1 == script.end());
8888
}
8989

90-
bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::vector<unsigned char> >& vSolutionsRet)
90+
txnouttype Solver(const CScript& scriptPubKey, std::vector<std::vector<unsigned char>>& vSolutionsRet)
9191
{
9292
vSolutionsRet.clear();
9393

9494
// Shortcut for pay-to-script-hash, which are more constrained than the other types:
9595
// it is always OP_HASH160 20 [20 byte hash] OP_EQUAL
9696
if (scriptPubKey.IsPayToScriptHash())
9797
{
98-
typeRet = TX_SCRIPTHASH;
9998
std::vector<unsigned char> hashBytes(scriptPubKey.begin()+2, scriptPubKey.begin()+22);
10099
vSolutionsRet.push_back(hashBytes);
101-
return true;
100+
return TX_SCRIPTHASH;
102101
}
103102

104103
int witnessversion;
105104
std::vector<unsigned char> witnessprogram;
106105
if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
107106
if (witnessversion == 0 && witnessprogram.size() == WITNESS_V0_KEYHASH_SIZE) {
108-
typeRet = TX_WITNESS_V0_KEYHASH;
109107
vSolutionsRet.push_back(witnessprogram);
110-
return true;
108+
return TX_WITNESS_V0_KEYHASH;
111109
}
112110
if (witnessversion == 0 && witnessprogram.size() == WITNESS_V0_SCRIPTHASH_SIZE) {
113-
typeRet = TX_WITNESS_V0_SCRIPTHASH;
114111
vSolutionsRet.push_back(witnessprogram);
115-
return true;
112+
return TX_WITNESS_V0_SCRIPTHASH;
116113
}
117114
if (witnessversion != 0) {
118-
typeRet = TX_WITNESS_UNKNOWN;
119115
vSolutionsRet.push_back(std::vector<unsigned char>{(unsigned char)witnessversion});
120116
vSolutionsRet.push_back(std::move(witnessprogram));
121-
return true;
117+
return TX_WITNESS_UNKNOWN;
122118
}
123-
typeRet = TX_NONSTANDARD;
124-
return false;
119+
return TX_NONSTANDARD;
125120
}
126121

127122
// Provably prunable, data-carrying output
@@ -130,47 +125,39 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::v
130125
// byte passes the IsPushOnly() test we don't care what exactly is in the
131126
// script.
132127
if (scriptPubKey.size() >= 1 && scriptPubKey[0] == OP_RETURN && scriptPubKey.IsPushOnly(scriptPubKey.begin()+1)) {
133-
typeRet = TX_NULL_DATA;
134-
return true;
128+
return TX_NULL_DATA;
135129
}
136130

137131
std::vector<unsigned char> data;
138132
if (MatchPayToPubkey(scriptPubKey, data)) {
139-
typeRet = TX_PUBKEY;
140133
vSolutionsRet.push_back(std::move(data));
141-
return true;
134+
return TX_PUBKEY;
142135
}
143136

144137
if (MatchPayToPubkeyHash(scriptPubKey, data)) {
145-
typeRet = TX_PUBKEYHASH;
146138
vSolutionsRet.push_back(std::move(data));
147-
return true;
139+
return TX_PUBKEYHASH;
148140
}
149141

150142
unsigned int required;
151143
std::vector<std::vector<unsigned char>> keys;
152144
if (MatchMultisig(scriptPubKey, required, keys)) {
153-
typeRet = TX_MULTISIG;
154145
vSolutionsRet.push_back({static_cast<unsigned char>(required)}); // safe as required is in range 1..16
155146
vSolutionsRet.insert(vSolutionsRet.end(), keys.begin(), keys.end());
156147
vSolutionsRet.push_back({static_cast<unsigned char>(keys.size())}); // safe as size is in range 1..16
157-
return true;
148+
return TX_MULTISIG;
158149
}
159150

160151
vSolutionsRet.clear();
161-
typeRet = TX_NONSTANDARD;
162-
return false;
152+
return TX_NONSTANDARD;
163153
}
164154

165155
bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
166156
{
167157
std::vector<valtype> vSolutions;
168-
txnouttype whichType;
169-
if (!Solver(scriptPubKey, whichType, vSolutions))
170-
return false;
158+
txnouttype whichType = Solver(scriptPubKey, vSolutions);
171159

172-
if (whichType == TX_PUBKEY)
173-
{
160+
if (whichType == TX_PUBKEY) {
174161
CPubKey pubKey(vSolutions[0]);
175162
if (!pubKey.IsValid())
176163
return false;
@@ -212,11 +199,11 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
212199
bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet)
213200
{
214201
addressRet.clear();
215-
typeRet = TX_NONSTANDARD;
216202
std::vector<valtype> vSolutions;
217-
if (!Solver(scriptPubKey, typeRet, vSolutions))
203+
typeRet = Solver(scriptPubKey, vSolutions);
204+
if (typeRet == TX_NONSTANDARD) {
218205
return false;
219-
if (typeRet == TX_NULL_DATA){
206+
} else if (typeRet == TX_NULL_DATA) {
220207
// This is data, not addresses
221208
return false;
222209
}
@@ -324,14 +311,12 @@ CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys)
324311

325312
CScript GetScriptForWitness(const CScript& redeemscript)
326313
{
327-
txnouttype typ;
328314
std::vector<std::vector<unsigned char> > vSolutions;
329-
if (Solver(redeemscript, typ, vSolutions)) {
330-
if (typ == TX_PUBKEY) {
331-
return GetScriptForDestination(WitnessV0KeyHash(Hash160(vSolutions[0].begin(), vSolutions[0].end())));
332-
} else if (typ == TX_PUBKEYHASH) {
333-
return GetScriptForDestination(WitnessV0KeyHash(vSolutions[0]));
334-
}
315+
txnouttype typ = Solver(redeemscript, vSolutions);
316+
if (typ == TX_PUBKEY) {
317+
return GetScriptForDestination(WitnessV0KeyHash(Hash160(vSolutions[0].begin(), vSolutions[0].end())));
318+
} else if (typ == TX_PUBKEYHASH) {
319+
return GetScriptForDestination(WitnessV0KeyHash(vSolutions[0]));
335320
}
336321
return GetScriptForDestination(WitnessV0ScriptHash(redeemscript));
337322
}

src/script/standard.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,11 +135,10 @@ const char* GetTxnOutputType(txnouttype t);
135135
* script hash, for P2PKH it will contain the key hash, etc.
136136
*
137137
* @param[in] scriptPubKey Script to parse
138-
* @param[out] typeRet The script type
139138
* @param[out] vSolutionsRet Vector of parsed pubkeys and hashes
140-
* @return True if script matches standard template
139+
* @return The script type. TX_NONSTANDARD represents a failed solve.
141140
*/
142-
bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::vector<unsigned char> >& vSolutionsRet);
141+
txnouttype Solver(const CScript& scriptPubKey, std::vector<std::vector<unsigned char>>& vSolutionsRet);
143142

144143
/**
145144
* Parse a standard scriptPubKey for the destination address. Assigns result to

0 commit comments

Comments
 (0)