aboutsummaryrefslogtreecommitdiff
path: root/src/script
diff options
context:
space:
mode:
authorPieter Wuille <pieter@wuille.net>2022-01-12 11:03:17 -0500
committerPieter Wuille <pieter@wuille.net>2022-01-12 11:08:19 -0500
commit25e95f9ff89a97b87ce218f28274c3c821b2d54d (patch)
tree7339f3c062ca3e5daeb92543e61843081648fb9e /src/script
parent16781e1bc9f8ffc721ebea73434e0066957bc959 (diff)
downloadbitcoin-25e95f9ff89a97b87ce218f28274c3c821b2d54d.tar.xz
Merge/generalize IsValidMultisigKeyCount/GetMultisigKeyCount
Diffstat (limited to 'src/script')
-rw-r--r--src/script/standard.cpp38
1 files changed, 18 insertions, 20 deletions
diff --git a/src/script/standard.cpp b/src/script/standard.cpp
index 5fb98cc307..0dd8eba1ba 100644
--- a/src/script/standard.cpp
+++ b/src/script/standard.cpp
@@ -96,47 +96,45 @@ static constexpr bool IsPushdataOp(opcodetype opcode)
return opcode > OP_FALSE && opcode <= OP_PUSHDATA4;
}
-static constexpr bool IsValidMultisigKeyCount(int n_keys)
-{
- return n_keys > 0 && n_keys <= MAX_PUBKEYS_PER_MULTISIG;
-}
-
-static bool GetMultisigKeyCount(opcodetype opcode, valtype data, int& count)
+/** Retrieve a minimally-encoded number in range [min,max] from an (opcode, data) pair,
+ * whether it's OP_n or through a push. */
+static std::optional<int> GetScriptNumber(opcodetype opcode, valtype data, int min, int max)
{
+ int count;
if (IsSmallInteger(opcode)) {
count = CScript::DecodeOP_N(opcode);
- return IsValidMultisigKeyCount(count);
- }
-
- if (IsPushdataOp(opcode)) {
- if (!CheckMinimalPush(data, opcode)) return false;
+ } else if (IsPushdataOp(opcode)) {
+ if (!CheckMinimalPush(data, opcode)) return {};
try {
count = CScriptNum(data, /* fRequireMinimal = */ true).getint();
- return IsValidMultisigKeyCount(count);
} catch (const scriptnum_error&) {
- return false;
+ return {};
}
+ } else {
+ return {};
}
-
- return false;
+ if (count < min || count > max) return {};
+ return count;
}
static bool MatchMultisig(const CScript& script, int& required_sigs, std::vector<valtype>& pubkeys)
{
opcodetype opcode;
valtype data;
- int num_keys;
CScript::const_iterator it = script.begin();
if (script.size() < 1 || script.back() != OP_CHECKMULTISIG) return false;
- if (!script.GetOp(it, opcode, data) || !GetMultisigKeyCount(opcode, data, required_sigs)) return false;
+ if (!script.GetOp(it, opcode, data)) return false;
+ auto req_sigs = GetScriptNumber(opcode, data, 1, MAX_PUBKEYS_PER_MULTISIG);
+ if (!req_sigs) return false;
+ required_sigs = *req_sigs;
while (script.GetOp(it, opcode, data) && CPubKey::ValidSize(data)) {
pubkeys.emplace_back(std::move(data));
}
- if (!GetMultisigKeyCount(opcode, data, num_keys)) return false;
-
- if (pubkeys.size() != static_cast<unsigned long>(num_keys) || num_keys < required_sigs) return false;
+ auto num_keys = GetScriptNumber(opcode, data, required_sigs, MAX_PUBKEYS_PER_MULTISIG);
+ if (!num_keys) return false;
+ if (pubkeys.size() != static_cast<unsigned long>(*num_keys)) return false;
return (it + 1 == script.end());
}