@@ -96,47 +96,45 @@ static constexpr bool IsPushdataOp(opcodetype opcode)
96
96
return opcode > OP_FALSE && opcode <= OP_PUSHDATA4;
97
97
}
98
98
99
- static constexpr bool IsValidMultisigKeyCount (int n_keys)
100
- {
101
- return n_keys > 0 && n_keys <= MAX_PUBKEYS_PER_MULTISIG;
102
- }
103
-
104
- static bool GetMultisigKeyCount (opcodetype opcode, valtype data, int & count)
99
+ /* * Retrieve a minimally-encoded number in range [min,max] from an (opcode, data) pair,
100
+ * whether it's OP_n or through a push. */
101
+ static std::optional<int > GetScriptNumber (opcodetype opcode, valtype data, int min, int max)
105
102
{
103
+ int count;
106
104
if (IsSmallInteger (opcode)) {
107
105
count = CScript::DecodeOP_N (opcode);
108
- return IsValidMultisigKeyCount (count);
109
- }
110
-
111
- if (IsPushdataOp (opcode)) {
112
- if (!CheckMinimalPush (data, opcode)) return false ;
106
+ } else if (IsPushdataOp (opcode)) {
107
+ if (!CheckMinimalPush (data, opcode)) return {};
113
108
try {
114
109
count = CScriptNum (data, /* fRequireMinimal = */ true ).getint ();
115
- return IsValidMultisigKeyCount (count);
116
110
} catch (const scriptnum_error&) {
117
- return false ;
111
+ return {} ;
118
112
}
113
+ } else {
114
+ return {};
119
115
}
120
-
121
- return false ;
116
+ if (count < min || count > max) return {};
117
+ return count ;
122
118
}
123
119
124
120
static bool MatchMultisig (const CScript& script, int & required_sigs, std::vector<valtype>& pubkeys)
125
121
{
126
122
opcodetype opcode;
127
123
valtype data;
128
- int num_keys;
129
124
130
125
CScript::const_iterator it = script.begin ();
131
126
if (script.size () < 1 || script.back () != OP_CHECKMULTISIG) return false ;
132
127
133
- if (!script.GetOp (it, opcode, data) || !GetMultisigKeyCount (opcode, data, required_sigs)) return false ;
128
+ if (!script.GetOp (it, opcode, data)) return false ;
129
+ auto req_sigs = GetScriptNumber (opcode, data, 1 , MAX_PUBKEYS_PER_MULTISIG);
130
+ if (!req_sigs) return false ;
131
+ required_sigs = *req_sigs;
134
132
while (script.GetOp (it, opcode, data) && CPubKey::ValidSize (data)) {
135
133
pubkeys.emplace_back (std::move (data));
136
134
}
137
- if (! GetMultisigKeyCount ( opcode, data, num_keys)) return false ;
138
-
139
- if (pubkeys.size () != static_cast <unsigned long >(num_keys) || num_keys < required_sigs ) return false ;
135
+ auto num_keys = GetScriptNumber ( opcode, data, required_sigs, MAX_PUBKEYS_PER_MULTISIG) ;
136
+ if (!num_keys) return false ;
137
+ if (pubkeys.size () != static_cast <unsigned long >(* num_keys)) return false ;
140
138
141
139
return (it + 1 == script.end ());
142
140
}
0 commit comments