Skip to content

Commit 3619735

Browse files
committed
Track difference between scriptPubKey and P2SH execution in IsMine
Inside IsMine we care about the distinction between scriptPubKey execution and P2SH redeemScript execution. The consensus code does not care about this distinction, and thus SigVersion does not have a field for P2SH. As the IsMine code will care, it uses a separate enum with more fields.
1 parent ac6ec62 commit 3619735

File tree

1 file changed

+19
-7
lines changed

1 file changed

+19
-7
lines changed

src/script/ismine.cpp

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,24 @@
1313

1414
typedef std::vector<unsigned char> valtype;
1515

16+
/**
17+
* This is an enum that tracks the execution context of a script, similar to
18+
* SigVersion in script/interpreter. It is separate however because we want to
19+
* distinguish between top-level scriptPubKey execution and P2SH redeemScript
20+
* execution (a distinction that has no impact on consensus rules).
21+
*/
1622
enum class IsMineSigVersion
1723
{
18-
BASE = 0,
19-
WITNESS_V0 = 1
24+
TOP = 0, //! scriptPubKey execution
25+
P2SH = 1, //! P2SH redeemScript
26+
WITNESS_V0 = 2 //! P2WSH witness script execution
2027
};
2128

29+
static bool PermitsUncompressed(IsMineSigVersion sigversion)
30+
{
31+
return sigversion == IsMineSigVersion::TOP || sigversion == IsMineSigVersion::P2SH;
32+
}
33+
2234
static bool HaveKeys(const std::vector<valtype>& pubkeys, const CKeyStore& keystore)
2335
{
2436
for (const valtype& pubkey : pubkeys) {
@@ -49,7 +61,7 @@ static isminetype IsMineInner(const CKeyStore& keystore, const CScript& scriptPu
4961
break;
5062
case TX_PUBKEY:
5163
keyID = CPubKey(vSolutions[0]).GetID();
52-
if (sigversion != IsMineSigVersion::BASE && vSolutions[0].size() != 33) {
64+
if (!PermitsUncompressed(sigversion) && vSolutions[0].size() != 33) {
5365
isInvalid = true;
5466
return ISMINE_NO;
5567
}
@@ -71,7 +83,7 @@ static isminetype IsMineInner(const CKeyStore& keystore, const CScript& scriptPu
7183
}
7284
case TX_PUBKEYHASH:
7385
keyID = CKeyID(uint160(vSolutions[0]));
74-
if (sigversion != IsMineSigVersion::BASE) {
86+
if (!PermitsUncompressed(sigversion)) {
7587
CPubKey pubkey;
7688
if (keystore.GetPubKey(keyID, pubkey) && !pubkey.IsCompressed()) {
7789
isInvalid = true;
@@ -86,7 +98,7 @@ static isminetype IsMineInner(const CKeyStore& keystore, const CScript& scriptPu
8698
CScriptID scriptID = CScriptID(uint160(vSolutions[0]));
8799
CScript subscript;
88100
if (keystore.GetCScript(scriptID, subscript)) {
89-
isminetype ret = IsMineInner(keystore, subscript, isInvalid, IsMineSigVersion::BASE);
101+
isminetype ret = IsMineInner(keystore, subscript, isInvalid, IsMineSigVersion::P2SH);
90102
if (ret == ISMINE_SPENDABLE || ret == ISMINE_WATCH_SOLVABLE || (ret == ISMINE_NO && isInvalid))
91103
return ret;
92104
}
@@ -117,7 +129,7 @@ static isminetype IsMineInner(const CKeyStore& keystore, const CScript& scriptPu
117129
// them) enable spend-out-from-under-you attacks, especially
118130
// in shared-wallet situations.
119131
std::vector<valtype> keys(vSolutions.begin()+1, vSolutions.begin()+vSolutions.size()-1);
120-
if (sigversion != IsMineSigVersion::BASE) {
132+
if (!PermitsUncompressed(sigversion)) {
121133
for (size_t i = 0; i < keys.size(); i++) {
122134
if (keys[i].size() != 33) {
123135
isInvalid = true;
@@ -141,7 +153,7 @@ static isminetype IsMineInner(const CKeyStore& keystore, const CScript& scriptPu
141153

142154
isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey, bool& isInvalid)
143155
{
144-
return IsMineInner(keystore, scriptPubKey, isInvalid, IsMineSigVersion::BASE);
156+
return IsMineInner(keystore, scriptPubKey, isInvalid, IsMineSigVersion::TOP);
145157
}
146158

147159
isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey)

0 commit comments

Comments
 (0)